Adding Asterisk to required fields on a form helps the user to quickly identify the required fields. Adding a star(*) is now an industrial standard that is required in almost every data-centric application consuming any kind of data.
For lengthy form it becomes a cumbersome job to add star sign to every form of control. Here we will discuss how to create a custom Angular 2+ directive to automatically add an asterisk(*) sign to required field controls like Input, Textarea, Radio, Checkboxes, and Select boxes.
Bootstrap with Angular is widely used these days and becoming one of the top choices for application building. Our form for demonstration will use Bootstrap classes to build a form with the basic control type we discussed and most of them will be having required HTML attributes.
Our addAsterisk
Directive will add an asterisk(*) on Form Field controls with the required attribute.
Let’s start creating our Directive, we will also get to know, how to create a directive which can be injected anywhere in the multi-module based application with its own module.
Create Directive
Directives in Angular are simple classes with a @Directive decorator in them which differentiates them from a normal class component.
Using NG CLI tool you can easily create a new directive by running following command in terminal:
$ng generate directive directives/mark-asterisk
Above command will create a new directive MarkAsteriskDirective
as shown below in the ~directives/mark-asterisk.directive.ts file:
import { Directive } from '@angular/core';
@Directive({
selector: '[appMarkAsterisk]'
})
export class MarkAsteriskDirective {
constructor() { }
}
In @Directive
decorator, we define some meta-information about the selector on which this directive will work.
To keep implementation easy we will use <strong>[required]</strong>
selector property in meta information so that there will not much work left to do in template across the application.
Change it as shown below:
import { Directive } from '@angular/core';
@Directive({
selector: '[required]'
})
export class MarkAsteriskDirective {
constructor() {}
}
Make Changes in Directive
Now to add an asterisk (*) on form control label we will use Renderer2
and ElementRef
classes in our directive with OnInit component life cycle hook.
Import them and add in the constructor as shown below:
import { Directive, OnInit, ElementRef, Renderer2 } from '@angular/core';
@Directive({
selector: '[required]'
})
export class MarkAsteriskDirective implements OnInit {
constructor(
private renderer: Renderer2,
private el: ElementRef
) {}
ngOnInit() {
...
...
}
}
In the template we will have Bootstrap form element as shown below:
<div class="form-group">
<label>Text Field</label>
<input type="email" class="form-control" required>
</div>
In the above HTML code, we need to append <span class="required-asterisk">*</span>
in
<div class="form-group">
<label>Text Field
<span class="required-asterisk">*</span>
</label>
<input type="email" class="form-control" required>
</div>
Basically in our directive, we need to look up to the parent tag of our selector which is [required], after finding the immediate parent we will find the LABEL
element then append <span>
with * sign.
Final Directive
Our final directive will look like this:
import { Directive, OnInit, ElementRef, Renderer2 } from '@angular/core';
@Directive({
selector: '[required]'
})
export class MarkAsteriskDirective implements OnInit {
constructor(private renderer: Renderer2, private el: ElementRef) {}
ngOnInit() {
const parent = this.renderer.parentNode(this.el.nativeElement);
if (parent.getElementsByTagName('LABEL').length && !parent.getElementsByClassName('required-asterisk').length) {
parent.getElementsByTagName('LABEL')[0].innerHTML += '<span class="required-asterisk">*</span>';
}
}
}
Add the following CSS style as well in styles.css file:
.required-asterisk{
color: red;
font-weight: bold;
margin-left: 3px;
font-size: 1.2em;
}
Declare Directive in Module
Make sure to add above directive in the app.module.ts file at declarations
array:
// app.module.ts
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { HttpClientModule } from '@angular/common/http';
import { BootstrapFormComponent } from './bootstrap-form/bootstrap-form.component';
import { MarkAsteriskDirective } from './directives/mark-asterisk.directive';
@NgModule({
declarations: [
AppComponent,
BootstrapFormComponent,
MarkAsteriskDirective
],
imports: [
BrowserModule,
AppRoutingModule,
HttpClientModule
],
providers: [
],
bootstrap: [AppComponent]
})
export class AppModule { }
That’s it! Look for bonus tip below:
How to use Directive as Shared Module?
Sometime you may have multiple modules with their own components, in that case, to easily inject a directive, we can create its own module.
So, after creating the Directive’s own module we DON’T need to add a directive in the declaration, instead, we will add the directive module in import array.
For this modular practice add @NgModule in the directive as shown below:
import { Directive, OnInit, ElementRef, Renderer2, NgModule } from '@angular/core';
@Directive({
selector: '[required]'
})
export class MarkAsteriskDirective implements OnInit {
constructor(private renderer: Renderer2, private el: ElementRef) {}
ngOnInit() {
const parent = this.renderer.parentNode(this.el.nativeElement);
if (parent.getElementsByTagName('LABEL').length && !parent.getElementsByClassName('required-asterisk').length) {
parent.getElementsByTagName('LABEL')[0].innerHTML += '<span class="required-asterisk">*</span>';
}
}
}
@NgModule({
declarations: [ MarkAsteriskDirective ],
exports: [ MarkAsteriskDirective ]
})
export class MarkAsteriskDirectiveModule {}
In the app.module.ts file or any other module, you can add this directive’s module in the imports
array to use in any component of this module.
// app.module.ts
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { HttpClientModule } from '@angular/common/http';
import { BootstrapFormComponent } from './bootstrap-form/bootstrap-form.component';
import {
// MarkAsteriskDirective,
MarkAsteriskDirectiveModule } from './directives/mark-asterisk.directive';
@NgModule({
declarations: [
AppComponent,
BootstrapFormComponent,
// MarkAsteriskDirective
],
imports: [
BrowserModule,
AppRoutingModule,
HttpClientModule,
MarkAsteriskDirectiveModule
],
providers: [
],
bootstrap: [AppComponent]
})
export class AppModule { }
Conclusion
So in the above tutorial, we learned how to create a Modular directive to add an asterisk(*) sign for required fields on form controls. After adding the directive, it will check all controls for the required property and append the span with an asterisk sign.
Leave a Reply