In this article we’ll see how to create a custom attribute directive in Angular. Attribute directive is used to modify the appearance or behavior of DOM element.
Angular provides a class named ElementRef which is a wrapper class around a native element inside of a View so it can access DOM. Permitting direct access to the DOM can make your application more vulnerable to XSS (Cross-Site Scripting) attacks. It is recommended to create a custom directive and use ElementRef class inside it to change the appearance or behavior of DOM element.
In Angular there is also a Renderer2 class that helps in implementing custom rendering. So in our custom attribute directive we'll make use of the Renderer2 and ElementRef classes to manipulate elements.
Steps to create a custom directive in Angular
1. Create a class decorated with @Directive.
You can use the following command to create a Directive class.
ng generate directive customdirective
It will generate customdirective.directive.ts Typescript file, a test file customdirective.directive.spec.ts and also updates app.module.ts to register the created directive.
Generated Directive class-
import { Directive } from '@angular/core'; @Directive({ selector: '[appCustomdirective]' }) export class CustomdirectiveDirective { constructor() { } }
You can notice that the selector for the directive is enclosed in square brackets [''] which means that the selector name passed will be a property of an element, not used as an element itself.
Custom attribute directive in Angular example
In this example we’ll create a custom directive that will set the background color for the element where it is used. Later we’ll make changes in the directive to make it react to the user events, pass value to it.
Custom directive with changes to set the background color style for the host element.
import { Directive, ElementRef, Renderer2 } from '@angular/core'; @Directive({ selector: '[appCustomdirective]' }) export class CustomdirectiveDirective { constructor(private el: ElementRef, private renderer: Renderer2) { this.highLight('yellow'); } private highLight(color : string){ this.renderer.setStyle(this.el.nativeElement,'backgroundColor',color); } }
In the constructor instance of ElementRef and Renderer2 are injected using dependency injection.
There is a highLight() method where setStyle() method of the Renderer2 is called to set the backgroundColor style of the host element. Host element is the element where this directive will be placed.
Applying an attribute directive
Let's add the selector of the directive in an element to see our custom directive in action.
Add the following in app.component.html. Here <span> is the host element which is using directive as an attribute.
<p>This content is highlighted using a <span appCustomdirective>custom directive</span></p>
Now if we compile and run our app-
Handling user events in custom directive
Now we have a directive that sets the background style of the host element. Let’s extend this functionality to set the style based on a user event.
There is a @HostListener decorator in Angular that declares a DOM event to listen for, and provides a handler method to run when that event occurs.
Using @HostListener decorator we’ll listen to 'mouseenter' and 'mouseleave' events in our custom directive and also provide handler methods to set the background style when these events occur.
import { Directive, ElementRef, HostListener, Renderer2 } from '@angular/core'; @Directive({ selector: '[appCustomdirective]' }) export class CustomdirectiveDirective { constructor(private el: ElementRef, private renderer: Renderer2) { //this.highLight('yellow'); } @HostListener('mouseenter') onMouseEnter() { this.highLight('yellow'); } @HostListener('mouseleave') onMouseLeave() { this.highLight(''); } private highLight(color : string){ this.renderer.setStyle(this.el.nativeElement,'backgroundColor',color); } }
As you can see there are two handler methods-
- onMouseEnter()- To listen to 'mouseenter' event.
- onMouseLeave()- To listen to 'mouseleave' event.
With that change you will see that “custom directive” text get highlighted only when you bring mouse over it.
Setting host element property in custom directive
In Angular there is a @HostBinding() Decorator that binds the host property. Angular automatically checks host property bindings during change detection, and if a binding changes it updates the host element of the directive.
Using @HostBinding decorator we’ll bind to the properties of the host element from the directive class and manipulate the host element using that bound property.
import { Directive, ElementRef, HostBinding, HostListener, Renderer2 } from '@angular/core'; @Directive({ selector: '[appCustomdirective]' }) export class CustomdirectiveDirective { constructor(private el: ElementRef, private renderer: Renderer2 { } @HostBinding('style.border') border: string; @HostListener('mouseenter') onMouseEnter() { this.highLight('yellow'); this.border = '2px dashed green'; } @HostListener('mouseleave') onMouseLeave() { this.highLight(''); this.border = ''; } private highLight(color : string){ this.renderer.setStyle(this.el.nativeElement,'backgroundColor',color); } }
In the custom directive using @HostBinding decorator style.border property of the host element is bound to the border property of the Directive class. Now, if a bound property changes that change is also reflected in the host element of the directive.
When this assignment this.border = '2px dashed green'; is done style.property of the host element is also updated.
Passing values into an attribute directive
You can also pass values to the directive using the @Input decorator. Using this feature let’s change the custom directive to pass the background style color to the directive rather than having a fixed value in the directive.
import { Directive, ElementRef, HostBinding, HostListener, Input, Renderer2 } from '@angular/core'; @Directive({ selector: '[appCustomdirective]' }) export class CustomdirectiveDirective { @Input('appCustomdirective') highlightColor: string; constructor(private el: ElementRef, private renderer: Renderer2) { } @HostBinding('style.border') border: string; @HostListener('mouseenter') onMouseEnter() { this.highLight(this.highlightColor); this.border = '2px dashed green'; } @HostListener('mouseleave') onMouseLeave() { this.highLight(''); this.border = ''; } private highLight(color : string){ this.renderer.setStyle(this.el.nativeElement,'backgroundColor',color); } }
A property “highlightColor” is added in the custom directive decorated with @Input decorator. It also uses the alias with the same name as the directive’s selector so that the same attribute can be used to apply directive and pass data.
Change in app.component.html to pass the color value.
<p>This content is highlighted using a <span [appCustomdirective]="'orange'">custom directive</span></p>
That's all for this topic How to Create a Custom Attribute Directive in Angular. If you have any doubt or any suggestions to make please drop a comment. Thanks!
>>>Return to Angular Tutorial Page
Related Topics
You may also like-
No comments:
Post a Comment