Introduction To Custom Attribute Directives In Angular 6

Introduction
 
In this session, I will show you how we can change appearances such as text color, background color and font size of a body of an HTML element using custom attribute directive.
 
To know details about Angular 6 visit my below links,
Description
 
We can create custom attribute directives and custom structural directives using a @Directive decorator. Using custom attribute directive we can change appearances such as text color, background color and font size of a body of an HTML element that can be called the host element. To change appearance Angular provides ElementRef class that can directly access DOM. It is vulnerable to XSS attacks when we directly use ElementRef in our application. It is better to create a custom directive and use ElementRef inside the directive to change the appearance or behavior of the host element.
 
Steps to create a custom attribute directive
  1. Create a class decorated with @Directive.
  2. Assign the attribute directive name to the selector metadata of @Directive decorator.
  3. Use ElementRef class to access DOM to change host element appearance and behavior.
  4. Use @Input() decorator to accept user input in our custom directive.
  5. Use @HostListener() decorator to listen to events in custom attribute directive.
  6. Configure custom attribute directive class in the application module in the declarations metadata of @NgModule.
Note 
I already have shown you how to create a custom attribute directive and its related files in my previous article. Now instead of repeat previous steps, I will describe only the major points. So, I suggest you before going through this visit my article link as mentioned above.  
 
Custom attribute directives - Dynamic Color  
 
Here we will create an attribute directive named as dynamic color. It will accept two inputs for background color. Second input color will be default color and will be active in the first input if the color has not been given. Now see the code.
 
Code ref. of dynamic-color.directive.ts
  1. import { Directive, ElementRef, HostListener, Input } from '@angular/core';  
  2.   
  3. @Directive({   
  4.      selector: '[dynamicColor]'   
  5. })  
  6. export class DynamicColorDirective {  
  7.    @Input('dynamicColor') dynamicColor: string;  
  8.    @Input() defaultValue: string;  
  9.    constructor(private elRef: ElementRef) {  
  10.    }  
  11.    @HostListener('mouseover') onMouseOver() {  
  12.      this.changeBackgroundColor(this.dynamicColor || this.defaultValue);  
  13.    }  
  14.    @HostListener('mouseleave') onMouseLeave() {  
  15.      this.changeBackgroundColor('white');  
  16.    }  
  17.    private changeBackgroundColor(color: string) {  
  18.      this.elRef.nativeElement.style.backgroundColor = color;  
  19.    }    
  20. }   
Code Description
 
We will create an attribute directive that will accept user input as well listen to events. The role of @Input() decorator is to accept user input and the role of @HostListener() decorator is to listen to the event. Here we will create an attribute directive named as dynamic color. It will accept two inputs for background color. Second input color will be default color and will be active in the first input if the color has not been given.
 
Code Ref. Of app.component.html
  1. <div>  
  2.     <select [(ngModel)] ="myColor">  
  3.       <option value='' selected> Select Color </option>  
  4.       <option *ngFor = "let color of colors" [value] = "color">  
  5.           {{color}}  
  6.       </option>  
  7.     </select>  
  8.   <p [dynamicColor]="myColor" defaultValue="red"> dynamicColor Directive Demo</p>  
  9. </div>  
Code Description
 
The background color of the text of the host element can be selected from a select box and when the mouse event mouseover is fired, the background color will be displayed as selected in the select box. When the mouse leaves event is fired, a fixed color white will be displayed.
 
In the above code, colors and myColor are the properties defined in our component, that is app.component.ts
  1. import { Component } from '@angular/core';  
  2.   
  3. @Component({  
  4.    selector: 'Satya-App',  
  5.    templateUrl: './app.component.html'  
  6. })  
  7. export class AppComponent {   
  8.    txtsize = '25px';  
  9.    colors = ['CYAN''GREEN''YELLOW'];  
  10.    myColor = '';  
  11. }  
When we select no color, the color assigned to defaultValue will be active and when we select any color from the select box then that color will be active. 
 
OUTPUT
 
The background color will be displayed as selected in the selected color dropdown when the mouse event mouseover is fired.
 
 
When we select no color, the color assigned to defaultValue will be active.
 
 
Custom attribute directives - Mouseover and mouseleave events
 
Code ref. of mouse.directive.ts,
  1. import { Directive, ElementRef, HostListener } from '@angular/core';  
  2.   
  3. @Directive({   
  4.      selector: '[mouseAction]'   
  5. })  
  6. export class MouseActionDirective {  
  7.    constructor(private elRef: ElementRef) {   
  8.    }  
  9.    @HostListener('mouseover') onMouseOver() {  
  10.      this.changeBackgroundColor('orange');  
  11.    }  
  12.    @HostListener('mouseleave') onMouseLeave() {  
  13.      this.changeBackgroundColor('green');  
  14.    }  
  15.    private changeBackgroundColor(color: string) {  
  16.      this.elRef.nativeElement.style.backgroundColor = color;  
  17.    }    
  18. }   
Code Description
 
We can create custom attribute directive that will perform changes in appearance in DOM when an event is fired. To listen to any event we need to use @HostListener(), decorator. We need to assign event name to @HostListener() decorator. Here we will create an attribute directive that will change the background color of host element when mouseover and mouseleave events are fired.
 
Code Ref. of app.component.html
  1. <p mouseAction> mouseAction Directive Demo</p>  
Code Description
 
Here I have mentioned directive name mouseAction.
 
OUTPUT
 
On mouseover event.
 
 
On mouseleave event. 
 
 
Custom attribute directives - Customize theme property and default theme property
 
Code ref. of custom-theme.directive.ts,
  1. import { Directive, ElementRef, Input, AfterViewInit } from '@angular/core';  
  2.   
  3. @Directive({   
  4.      selector: '[customTheme]'   
  5. })  
  6. export class CustomThemeDirective implements AfterViewInit {  
  7.     @Input() tcolor: string;  
  8.     @Input() bcolor: string;  
  9.     @Input() tsize: string;   
  10.     constructor(private elRef: ElementRef) {  
  11.     }  
  12.     ngAfterViewInit(): void {  
  13.        this.tcolor = this.tcolor || 'white';  
  14.        this.bcolor = this.bcolor || 'orange';  
  15.        this.tsize = this.tsize || '20px';  
  16.        this.elRef.nativeElement.style.color = this.tcolor;  
  17.        this.elRef.nativeElement.style.backgroundColor = this.bcolor;  
  18.        this.elRef.nativeElement.style.fontSize = this.tsize;  
  19.     }     
  20. }   
Code Description
 
Here we will create an attribute directive that will accept more than one user input. To accept more than one user input, we need to use more than one @Input() decorated property in our class.
 
Code ref. of app.component.html
  1. <div customTheme> customTheme Directive Demo with Default Settings</div>  
  2. <div customTheme tcolor="yellow" bcolor="black" tsize="30px"> customTheme Directive Demo with Custom Settings</div>  
Code Description 
 
Here I have used a custom theme directive as follows. In the first one, the theme property can be customized using default settings and in the second one, theme property can be customized using custom user input settings.
 
OUTPUT
 
Here you can see both setting implementations in theme property.
 
SUMMARY
  • The concept behind custom attribute directive 
  • Attribute Directive using @Input() and @HostListener() for dynamic color.
  • Attribute Directive using @HostListener() to listen to Event for mouseover and mouseleave events
  • Attribute Directive using Multiple @Input() for customize theme property and default theme property.