Author avatar

Gaurav Singhal

Generating a Custom Directive with the CLI

Gaurav Singhal

  • Dec 5, 2019
  • 12 Min read
  • 240 Views
  • Dec 5, 2019
  • 12 Min read
  • 240 Views
Web Development
Angular

Introduction

In this guide, we are going to learn that what a custom directive is, how to create it, and where we can use such a custom directive in Angular. More importantly, we will learn it by creating and implementing a custom directive from scratch in through two examples.

The Custom Directive in Angular

Before getting into building a custom directive, we should understand what it is and why we should use a directive in our Angular application.

When we create an application using the CLI, we can have one root component, which is called an app component. It is also a directive itself, which is the basic building block of an entire application.

Angular supports three different types of directives:

  • Component directive s
  • Structural directive s
  • Attribute directive s

As we discussed earlier, a component itself is a component directive, so structural directives are used to add, update or conditionally render the different DOM elements, and at last the attribute directive comes into the picture. It is also called a custom directive and it allows us to use a directive as an element’s attribute and perform a specific action.

The custom directive, or attribute directive, are responsible for modifying the appearance or behavior of HTML elements, just like we use properties along with any element’s properties.

By default, in Angular, there are two types of in-built attribute directives supported:

  • NgStyle : This attribute directive is used to modify the appearance or behavior of the different DOM elements. It applies styles directly to the native element, such as font, font style, color, border, height, width, and so on.

  • NgClass : This attribute directive is used to modify or apply the class attribute to the native DOM elements by just providing the class name along with the attribute name.

So far, we have learned about the custom directive and the type of attribute directive. Now we can also create the custom directive based on the business requirements, so let’s create it.

Creating a Custom Directive using Angular CLI

The custom directive is nothing but the attribute directive, which allows us to change the behavior or appearance of an element by just providing the custom attribute and processing it.

In order to achieve this, we need to create a separate directive that gets the complete element, and we can process or modify it based on our requirements.

To create the custom directive, we can use Angular CLI. The command we need to execute is given below.

1
Ng generate directive <directive_name>
shell

This is how we can create the directive by providing the directive name, for example.

1
Ng generate directive mydirective
shell

Example 1

Now let’s look at a simple example where we will create a custom directive to change the font color of the label control by using our newly generated custom directive.

For that, we need to use the below command to create the directive.

1
Ng generate directive highlight
shell

After creating the directive, we need to import it into the module file. To do that, open app.module.ts, and the source code will look like this.:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { FormsModule } from '@angular/forms';
import { AppComponent } from './app.component';

// Importing the custom directive
import { HighlightDirective } from './highlight.directive';

@NgModule({
  imports:      [ BrowserModule, FormsModule ],
  declarations: [ AppComponent, HighlightDirective ],
  bootstrap:    [ AppComponent ]
})

export class AppModule { }
typescript

Where the highlight is the name of our directive, and after executing the above command, the new file will be created, and the code will look like this:

Highlight.directive.ts

1
2
3
4
5
6
7
8
9
import { Directive } from '@angular/core';

@Directive({
  selector: '[appHighlight]'
})

export class HighlightDirective {
  constructor() { }
}
typescript

As we can see in the above example, the file contains the keyword @Directive(), which declares the directive with the selector appHighlight, which we can use into the template in order to change the behavior of the element.

The question may arise about how to access the element from the directive. Well, for that, we can use ElementRef, which allows us to access the element from the template directly, just like this:

1
2
3
constructor(elementr: ElementRef) {  
  // can use elementr here to access the element properties
}  
typescript

Now let’s change the font color of a label element using the custom directive. Before that, open the file app.component.html and paste the following lines of code:

1
2
3
<div>
    <label appHighlight>This is label element</label>
</div>
html

Notice that we have used appHighlight as an attribute along with the label element. This means we have used the custom attribute which accesses the current element, and by using ElementRef, we can modify its behavior.

Let’s jump to our newly created directive called highlight.directive.ts and replace the following source code.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import { Directive, ElementRef } from "@angular/core";

@Directive({
  selector: "[appHighlight]"
})

export class HighlightDirective {

  constructor(private el: ElementRef) {
    // To change label's font color
    el.nativeElement.style.color = "red";
  }

}
typescript

By using this directive, we wcan change the font color of the label. For that, we have accessed the native element using ElementRef, thus now we will be able to modify its styles just like we have modified the color of the element with the custom value.

When we run this example, the label control’s font color will be red based on our requirement.

In the same way, we can also modify the different attributes of the same elements with different values like this:

1
2
3
4
5
6
7
8
9
10
export class HighlightDirective {
    
  constructor(private el: ElementRef) {
    // To change label's font color and other properties
    el.nativeElement.style.color = "red";
    el.nativeElement.style.fontWeight = "bolder";
    el.nativeElement.style.border = "2px double black";
  }
    
}
typescript

This is just a simple example that shows how to access the native element using the custom directive and how to modify the styles of the element directly from the custom attribute. You can try this example on your own and observe the changes you get.

Example 2

So far, we have seen how to create the directive using the Angular CLI and looked at a simple example to access and modify the styles of the element.

Now let’s jump to a more complex example where we will implement the directive which accepts the input value, and based on the length of the input value, we will change the background color of the input box directly from the custom directive.

Before digging into the example, we need to create a new custom directive. We can use the below command for that.

1
Ng generate directive passwordlengthdetector
shell

We have created our custom directive so far, and now before using that directive, we need to import it into the module file like this.

1
2
3
4
5
6
7
8
9
10
11
12
13
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { FormsModule } from '@angular/forms';
import { AppComponent } from './app.component';
import { PasswordlengthdetectorDirective } from './passwordlengthdetector.directive'

@NgModule({
  imports:      [ BrowserModule, FormsModule ],
  declarations: [ AppComponent, PasswordlengthdetectorDirective ],
  bootstrap:    [ AppComponent ]
})

export class AppModule { }
typescript

After creating the directive using the above command, we can see the newly created file like this:

Passwordlengthdetector.directive.ts

1
2
3
4
5
6
7
8
9
10
import { Directive } from '@angular/core';

@Directive({
  selector: '[appPasswordlengthdetector]'
})

export class PasswordlengthdetectorDirective {
  constructor() { }

}
typescript

So far, the basic configuration is done for our custom component. Now our requirement is to get the input value from the parent component and pass it to the directive for further processing. For that, let’s jump to the app.component.html, and the code will look like this.:

1
2
3
4
5
6
7
8
9
10
<table>
    <tr>
       <td>
         <label>Please enter your password :-</label>
       </td>
       <td>
         <input type="text" appPasswordlengthdetector />
       </td>
    </tr>
</table>
html

Here in this file, we have simple input control, but one thing to notice is that we have also used an additional attribute called appPasswordlengthdetector, which is our custom directive name. In this way, we are allowing our element to pass its value to the directive itself.

Let’s modify our custom directive so that it can change the behavior of the existing element based on our requirements.

appPasswordlengthdetector.directive.ts

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
import {
  Directive,
  ElementRef,
  OnChanges,
  HostListener
} from "@angular/core";

@Directive({
  selector: "[appPasswordlengthdetector]"
})

export class PasswordlengthdetectorDirective implements OnChanges {

  constructor(private el: ElementRef) {
    console.log(el.nativeElement.value);
  }

  // Listen for keyup event and change background color
  @HostListener("window:keyup") ngOnChanges(event) {

    let count = this.el.nativeElement.value.length
    console.log(this.el.nativeElement.value.length);
    if(count < 5) {
        this.el.nativeElement.style.backgroundColor = 'red'
    } else if(count >= 5 && count <= 10) {
        this.el.nativeElement.style.backgroundColor = 'green'
    } else if(count > 10) {
        this.el.nativeElement.style.backgroundColor = 'purple'
    }

  }

}
typescript

Let's break down the code step by step to understand.

  • The first step was to use the ElementRef so that we can access the current element from the template.
  • Then we used HostListener, a decorator in Angular which is used to listen for the event attached to the host element. It will be destroyed once the directive is unmounted.
  • Inside the HostListener event, we have accessed the native element using ElementRef’s object and will be modifying styles like backgroundcolor.

So when we change the input value based on the key up event, at that time, the value will be accessed from the directive, and the styles can be modified using the reference of the native element.

The background color will be changed based on the three conditions:

  • Red if the length of password < 5
  • Green if the length of password >=5 and <=10
  • Purple if the length of password > 10

This is how we have created our very own custom directive that accepts the input value and is based on the length of the same value. It will change the input’s background color to denote the strength of the password.

Conclusion

Custom directives are pretty handy when it comes to accessing inputs or elements and modifying their behavior and appearance.

In this guide, we got a basic introduction to custom directives, which are also called attribute directives, and the different types of directives are supported in Angular. We also looked at two different real-life examples that showed how to use custom directives into our Angular application. I hope you enjoyed this guide. Keep reading for more advanced guides in the future.

0