Angular 9|8|7 Add ( Star *) Asterisk Sign to Required Fields using Custom Directive for Bootstrap Form

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.

 

Angular 9|8|7 Add ( Star *) Asterisk Sign to Required Fields using Custom Directive for Bootstrap Form

 

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 [required] 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.

 

 

Subscribe
Notify of
guest
0 Comments
Inline Feedbacks
View all comments