Angular 8 Directives (Day 4)

In this article, we will discuss the concept of Directive in Angular 8. The directive is another main building block of the Angular framework. Using directive, we can create different reusable UI controls of the web application in which we can define design as well as business logic and those controls can be used in different components in the applications.
 

What is the Directive?

 
A directive modifies the DOM by changing the appearance, behavior, or layout of DOM elements. Directives just like Component are one of the core building blocks in the Angular framework to build applications. In fact, Angular 8 components are, in large part, directives with templates. In Angular 8 components have assumed a lot of the roles directives used to. In Angular 8, the major issues related to the template injection and dependency injection are solved with the help of components and issues related to the providing the modification for the generic behavior of the application is done by the help of directives.
 
So, if we consider the high-level definition of directives, then Directives are acts as a HTML markers on any DOM element (like as an attribute or element name or comment or CSS based style class) which instructed Angular’s HTML compiler to attach a specified behaviour on that particular DOM element or to transform that DOM element. 


Basic Concept of Directives


In Angular Framework, one of the most important elements is Directives. And if we analyze the directive in brief, then we will discover that the main building block of the Angular 8 framework which is known as Component is basically a directive. So, in a simple word, each and every Angular component is just a directive with a custom HTML template. So, in real word when defining a component as the main building block of Angular application, actually we want to say that directives are the main building blocks of Angular applications.

In general, a directive is a TypeScript based function that executes whenever Angular compiler identified it within the DOM element. Directives are used to provide or generate new HTML based syntax which will extend the power of the UI in an Angular Application. Each directive must have a selector name just like the same as a component – either that name can be from Angular predefined patterns like ng-if or a custom developer-defined name which can be any name but need to indicate the main purpose of the directive. Also, every directive can act as an element or an attribute or a class or a comment in the HTML section. 
 

Why Directives Required?


In Angular Framework, Directives always ensure the high-level of reusability of the UI controls throughout the application. With the help of Directives, we can develop UIs with many movable parts and at the same time, we can streamline the development flow for the engineers. The main reason for using directives in any Angular applications are – 
  1. Reusability – In an Angular application, the directive is a self-sufficient part of the UI. As a developer, we can reuse the directive across the different parts of the application. This is very much useful in any large-scale applications where multiple systems need the same functional elements like search box, date control, etc.
  2. Readability – Directive provides much more readability for the developers to understand the production functionality and data flow.
  3. Maintainability – One of the main use of directive in any application is the maintainability. We can easily decouple the directive from the application and replace the old one with a new one directives. 

Component vs Directives


The comparison between Component and directives are as below – 
 

Component

Directives

A component is defined with the @Component decorator

A Directive is defined with the @Directives decorator

A component is a directive that uses a shadow DOM to create encapsulated visual behavior called a component. Components are typically used to create UI widgets.

Directive mainly used to provide new behavior within the existing DOM elements.

With the help of the component, we can break down the application in multiple small parts.

With the help of the directive, we can design any type of reusable component.

In the browser DOM, only one component can be activated as a parent component. Other components will act like a child component in that case.

Within a single DOM element, any no of directives can be used.

@View decorator or templateUrl template is mandatory in the component.

Directives don’t use View.

 

@Directive Metadata


@Directive decorator is used to defining any class as an Angular Directive. We can always define any directive to specify the custom behavior of the elements within the DOM. @Directive() metadata is contained below-mentioned options – 
  1. selector – The selector property is used to identify the directive within the HTML template. Also, with the help of this property, we can initialize the directive from the DOM elements
  2. inputs - It is used to provide the set of data-bound input properties of the directives.
  3. outputs – It is used to enumerates any event properties from the directives.
  4. providers – It is used to inject any provider type like service or components within the directives.
  5. exportAs – It is used to define the name of the directives which can be used to assign a directive as a variable. 
 

Types of Directives


There are three main types of directives in Angular 8:
  • Component – Directives with templates.
  • Attribute Directives – Directives that change the behavior of a component or element but don’t affect the template.
  • Structural Directives – Directives that change the behavior of a component or element by affecting the template or the DOM decoration of the UI.
 

What is an Attribute Directive?


Attribute directives are mainly used for changing the appearance or behavior of a component or a native DOM element. Attribute directives actually modify the appearance or behavior of an element. These directives actually act as a simple HTML attribute for any HTML tag. There some inbuild attribute directive is available in the framework like ngModel. But, we can also create any type of custom attribute-based directive as per our requirement. In that case, use the attribute directive selector name as an attribute within the HTML tag in the HTML code section.  
 

In-Built Attribute Directives


Angular 8 provides some inbuilt Attribute directives which can be used to change the style or attributes of the HTML elements in the DOM. Those attribute directives are –
  • ngClass - ngClass directive changes the class attribute that is bound to the component or element it's attached to.
  • ngStyle - ngStyle is mainly used to modify or change the element’s style attribute. This attribute directive is quite similar to using style metadata in the component class.


What is Structural Directive?


Other types of directives in the Angular framework are the Structural Directive. Structural directives are mainly used to change the design pattern of the UI DOM elements. In HTML, these directives can be used as a template tag. Using this type of directives, we can change the structure of any DOM elements and can redesign or redecorate those DOM elements. In Angular Framework, there are some system generate structural directives is available like ngIf, ngFor and ngSwitch. We can also create any custom structural directive. The most common example of any custom structural directives is components. Since we can consider every component as a structural directive if that component makes some change in the UI DOM elements style or design. All the system generated structural directives have a template name along with some property value that needs to provide when we define that directives in the HTML code.  
 

In-Build Structural Directive


Angular 8 provides below mentioned built-in directives which can be used within a component to change the elements structure or design. 
  • ngIf
  • ngFor
  • ngSwitch 
 

Custom Directive

 
To create attribute directives, we always need to use or inject the below objects in our custom attribute directive component class. To create an attribute directive, we need to remember the below topics:
 
  1. Import required modules like directives, ElementRef, and renderer from the Angular core library.
  2. Create a TypeScript class.
  3. Use the @Directive decorator in the class.
  4. Set the value of the selector property in the @directive decorator function. The directive will be used, using the selector value on the elements.
  5. In the constructor of the class, inject ElementRef and the renderer object.
  6. You need to inject ElementRef in the directive’s constructor to access the DOM element.
  7. You also need to inject the renderer in the directive’s constructor to work with the DOM’s element style.
  8. You need to call the renderer’s setElementStyle function. In this function, we need to pass the instance of the current DOM element with the help of ElementRef as a parameter and setting the behavior or property of the current element.  

ElementRef- While creating a custom attribute directive, we inject ElementRef in the constructor to access the DOM element. ElementRef provides access to the underlying native element. With the help of ElementRef, we can obtain direct access to the DOM element using its nativeElement property. In that case, ElementRef is behaving just like a service. That’s all we need to set the element’s color using the browser DOM API.

Renderer- While creating a custom attribute directive, we inject Renderer in the constructor to access the DOM element’s style. Actually, we call the renderer’s setElementStyle function. In this function, we pass the current DOM element with the help of the ElementRef object and set the required attribute of the current element.
 
HostListener - Sometimes we may need to access the input property within the attribute directive so that, as per the given attribute directive, we can apply a related attribute within the DOM Element. To trap user actions, we can call different methods to handle user actions. We need to use this method to perform any user action. For that purpose, we need to decorate the method with @HostListener method.
 

Demo 1: Attribute Directive


Now in this demo, we will demonstrate how to use inbuilt attribute directives in Angular Framework.

app.component.ts 
  1. import { Component } from '@angular/core';  
  2.   
  3. @Component({  
  4.   selector: 'app-root',  
  5.   templateUrl: './app.component.html',  
  6.   styleUrls : ['./custom.css']  
  7. })  
  8. export class AppComponent {  
  9.     
  10.   showColor: boolean = false;  
  11.   
  12.   constructor() { }  
  13.   
  14.   public changeColor(): void {  
  15.       this.showColor = !this.showColor;  
  16.   }  
  17. }  
app.component.html
  1. <div>  
  2.     <h3>This is a Attribute Directives</h3>  
  3.     <span [class.red]="true">Attribute Change</span><br />  
  4.     <span [ngClass]="{'blue':true}">Attribute Change by Using NgClass</span><br />  
  5.     <span [ngStyle]="{'font-size':'14px','color':'green'}">Attribute Change by Using NgStyle</span>  
  6.     <br /><br />  
  7.     <span [class.cyan]="showColor">Attribute Change</span><br />  
  8.     <span [ngClass]="{'brown':showColor}">Attribute Change by Using NgClass</span><br />  
  9.     <input type="button" value="Change Color" (click)="changeColor()" />  
  10.     <br /><br />  
  11.     <span [class.cyan]="showColor">Attribute Change</span><br />  
  12.     <span [ngClass]="{'cyan':showColor, 'red' : !showColor}">Attribute Change by Using NgClass</span><br />  
  13.     <br />  
  14. </div>  
custom.css 
  1. .red {color:red;}  
  2. .blue {color:blue}  
  3. .cyan {color : cyan}  
  4. .brown {color : brown}  
Now check the output in the browser.
 

Demo 2: ngIf


Now in this demo, we will explain how to use ngIf in our angular application.
app.component.ts 
  1. import { Component } from '@angular/core';  
  2.   
  3. @Component({  
  4.   selector: 'app-root',  
  5.   templateUrl: './app.component.html',  
  6.   styleUrls : ['./custom.css']  
  7. })  
  8. export class AppComponent {  
  9.     
  10.   showInfo: boolean = false;  
  11.   caption: string = 'Show Text';  
  12.   
  13.   constructor() { }  
  14.   
  15.   public changeData(): void {  
  16.       this.showInfo = !this.showInfo;  
  17.       if (this.showInfo) {  
  18.           this.caption = 'Hide Text';  
  19.       }  
  20.       else {  
  21.           this.caption = 'Show Text';  
  22.       }  
  23.   }  
  24. }  
app.component.html
  1. <div>  
  2.     <input type="button" value="{{caption}}" (click)="changeData()"/>  
  3.     <br />  
  4.     <h2 *ngIf="showInfo"><span>Demonstrate of Structural Directives - *ngIf</span></h2>  
  5. </div>  
Now check the output in the browser.

Demo 3: ngFor


Now in this demo, we will explain how to use ngFor in our angular application.
app.component.ts 
  1. import { Component } from '@angular/core';  
  2.   
  3. @Component({  
  4.   selector: 'app-root',  
  5.   templateUrl: './app.component.html',  
  6.   styleUrls : ['./custom.css']  
  7. })  
  8. export class AppComponent {  
  9.     
  10.   productList: Array<string> = ['IPhone','Galaxy 9.0','Blackberry 10Z'];  
  11.   
  12.   constructor() { }  
  13. }  

app.component.html

  1. <div>  
  2.     <h2>Demonstrate ngFor</h2>  
  3.     <ul>  
  4.         <li *ngFor="let item of productList">  
  5.             {{item}}  
  6.         </li>  
  7.     </ul>  
  8. </div>  
Now check the output in the browser.
 

Demo 4: ngSwitch


Now in this demo, we will explain how to use ngSwitch in our angular application.
app.component.ts 
  1. import { Component, OnInit } from '@angular/core';  
  2.   
  3. @Component({  
  4.   selector: 'app-root',  
  5.   templateUrl: './app.component.html',  
  6.   styleUrls : ['./custom.css']  
  7. })  
  8. export class AppComponent implements OnInit {  
  9.     
  10.   studentList: Array<any> = new Array<any>();  
  11.   
  12.     constructor() { }  
  13.     ngOnInit() {  
  14.         this.studentList = [  
  15.             { SrlNo: 1, Name: 'Rajib Basak', Course: 'Bsc(Hons)', Grade: 'A' },  
  16.             { SrlNo: 2, Name: 'Rajib Basak1', Course: 'BA', Grade: 'B' },  
  17.             { SrlNo: 3, Name: 'Rajib Basak2', Course: 'BCom', Grade: 'A' },  
  18.             { SrlNo: 4, Name: 'Rajib Basak3', Course: 'Bsc-Hons', Grade: 'C' },  
  19.             { SrlNo: 5, Name: 'Rajib Basak4', Course: 'MBA', Grade: 'B' },  
  20.             { SrlNo: 6, Name: 'Rajib Basak5', Course: 'MSc', Grade: 'B' },  
  21.             { SrlNo: 7, Name: 'Rajib Basak6', Course: 'MBA', Grade: 'A' },  
  22.             { SrlNo: 8, Name: 'Rajib Basak7', Course: 'MSc.', Grade: 'C' },  
  23.             { SrlNo: 9, Name: 'Rajib Basak8', Course: 'MA', Grade: 'D' },  
  24.             { SrlNo: 10, Name: 'Rajib Basak9', Course: 'B.Tech', Grade: 'A' }  
  25.         ];  
  26.     }  
  27. }  
app.component.html
 
  1. <div>  
  2.     <h2>Demonstrate ngSwitch</h2>  
  3.     <table style="width:100%;border:solid;border-color:blue;border-width:thin;">  
  4.         <thead>  
  5.             <tr >  
  6.                 <td>Srl No</td>  
  7.                 <td>Student Name</td>  
  8.                 <td>Course</td>  
  9.                 <td>Grade</td>  
  10.             </tr>  
  11.         </thead>  
  12.         <tbody>  
  13.             <tr *ngFor="let student of studentList;" [ngSwitch]="student.Grade">  
  14.                 <td>  
  15.                     <span *ngSwitchCase="'A'" [ngStyle]="{'font-size':'18px','color':'red'}">{{student.SrlNo}}</span>  
  16.                     <span *ngSwitchCase="'B'" [ngStyle]="{'font-size':'16px','color':'blue'}">{{student.SrlNo}}</span>  
  17.                     <span *ngSwitchCase="'C'" [ngStyle]="{'font-size':'14px','color':'green'}">{{student.SrlNo}}</span>  
  18.                     <span *ngSwitchDefault [ngStyle]="{'font-size':'12px','color':'black'}">{{student.SrlNo}}</span>  
  19.                 </td>  
  20.                 <td>  
  21.                     <span *ngSwitchCase="'A'" [ngStyle]="{'font-size':'18px','color':'red'}">{{student.Name}}</span>  
  22.                     <span *ngSwitchCase="'B'" [ngStyle]="{'font-size':'16px','color':'blue'}">{{student.Name}}</span>  
  23.                     <span *ngSwitchCase="'C'" [ngStyle]="{'font-size':'14px','color':'green'}">{{student.Name}}</span>  
  24.                     <span *ngSwitchDefault [ngStyle]="{'font-size':'12px','color':'black'}">{{student.Name}}</span>  
  25.                 </td>  
  26.                 <td>  
  27.                     <span *ngSwitchCase="'A'" [ngStyle]="{'font-size':'18px','color':'red'}">{{student.Course}}</span>  
  28.                     <span *ngSwitchCase="'B'" [ngStyle]="{'font-size':'16px','color':'blue'}">{{student.Course}}</span>  
  29.                     <span *ngSwitchCase="'C'" [ngStyle]="{'font-size':'14px','color':'green'}">{{student.Course}}</span>  
  30.                     <span *ngSwitchDefault [ngStyle]="{'font-size':'12px','color':'black'}">{{student.Course}}</span>  
  31.                 </td>  
  32.                 <td>  
  33.                     <span *ngSwitchCase="'A'" [ngStyle]="{'font-size':'18px','color':'red'}">{{student.Grade}}</span>  
  34.                     <span *ngSwitchCase="'B'" [ngStyle]="{'font-size':'16px','color':'blue'}">{{student.Grade}}</span>  
  35.                     <span *ngSwitchCase="'C'" [ngStyle]="{'font-size':'14px','color':'green'}">{{student.Grade}}</span>  
  36.                     <span *ngSwitchDefault [ngStyle]="{'font-size':'12px','color':'black'}">{{student.Grade}}</span>  
  37.                 </td>  
  38.             </tr>  
  39.         </tbody>  
  40.     </table>  
  41. </div>  
Now check the output in the browser.
 

Demo 5: Custom Directive – Color Change


Now, in this demo, we will create a custom attribute based directives which will change the color of the selected text on mouseover. For that, we need to first create the directive below.
app.directive.ts 
  1. import { Directive, ElementRef, Renderer, HostListener, Input } from '@angular/core';  
  2.   
  3. @Directive({  
  4.     selector: '[colorchange]'  
  5. })  
  6. export class ColorChangeDirective {  
  7.     private _defaulColor = 'red';  
  8.     @Input('colorchange') highlightColor: string;  
  9.   
  10.     constructor(private el: ElementRef, private render: Renderer) {  
  11.     }  
  12.   
  13.     @HostListener('mouseenter') onMouseEnter() {  
  14.         console.log(this.highlightColor);  
  15.         this.changecolor(this.highlightColor || this._defaulColor);  
  16.     }  
  17.   
  18.     @HostListener('mouseleave') onMouseLeave() {  
  19.         console.log(this.highlightColor);  
  20.         this.changecolor(null);  
  21.     }  
  22.   
  23.     private changecolor(color: string) {  
  24.         this.render.setElementStyle(this.el.nativeElement, 'color', color);  
  25.     }  
  26. }  
Now, we need to use this custom directive in our app-root component as below.
app.component.ts
  1. import { Component } from '@angular/core';  
  2.   
  3. @Component({  
  4.   selector: 'app-root',  
  5.   templateUrl: './app.component.html',  
  6.   styleUrls : ['./custom.css']  
  7. })  
  8. export class AppComponent {  
  9.     
  10.   public message: string = 'Sample Demostration of Attribute Directives using Custom Directives';  
  11.   public color: string = 'blue';  
  12.   
  13. }  
app.component.html
  1. <div>  
  2.     <input type="radio" name="colors" (click)="color='blue'">blue  
  3.     <input type="radio" name="colors" (click)="color='orange'">orange  
  4.     <input type="radio" name="colors" (click)="color='green'">green  
  5. </div>  
  6. <h1 [colorchange]="color">{{message}}</h1>  
Now, include the above created custom directive in our AppModule as below –
  1. import { BrowserModule } from '@angular/platform-browser';  
  2. import { NgModule } from '@angular/core';  
  3. import { FormsModule } from '@angular/forms';  
  4.   
  5. import { AppComponent } from './app.component';  
  6. import { ColorChangeDirective } from './app.directive';  
  7.   
  8. @NgModule({  
  9.   declarations: [  
  10.     AppComponent,ColorChangeDirective  
  11.   ],  
  12.   imports: [  
  13.     BrowserModule,FormsModule  
  14.   ],  
  15.   providers: [],  
  16.   bootstrap: [AppComponent]  
  17. })  
  18. export class AppModule { }  
Now, run the output in the browser as below -
 
 
 

Conclusion

 
In this article, we discussed another main building block in Angular 8 e.i. Directives. Also, we discussed the different types of directives like attribute directives and structural directives. Now, in the next article, we will discuss another important part of Angular i.e. Pipe. I hope, this article will help you.
Author
Debasis Saha
3 69.6k 33.4m
Next » Angular 8 Pipes (Day 5)