Overview
In Angular, custom attribute directives are a fundamental building block for extending the functionality and behavior of your HTML elements. They allow you to create reusable, self-contained modules that can modify the appearance or behavior of DOM elements in your application. In this course chapter, we will dive deep into custom attribute directives, understanding how to create theme and leverage their power in your Angular applications.
Creating a Custom Attribute Directive Using Angular CLI
The Angular CLI simplifies the process of creating custom attribute directives. Let's create a directive named appSetBackground
to change an element's background color when hovered over:
Step 1: Generate the Directive
In your terminal, navigate to your Angular project's root folder and user the Angular CLI to generate a new directive:
ng generate directive setBackground
This command will create the appSetBackground
directive files in your project.
Step 2: Define the Directive Logic
Edit the set-background.directive.ts
file created by the CLI. The directive class should look like this:
We have two ways of achieving our target:
Traditional Method (nativeElement property)
nativeElement property gives us the direct access to DOM bypassing the angular, it is good but not advisable. below are the few reasons for it:
- Angular keeps the Component and view in Sync using Templates, data binding and change detection, etc. All of them bypassed when we update the DOM directly.
- DOM manipulation works only in Browser. you will not able to use the App in other platforms like in web worker, in Server, or in a Desktop, or in mobile app etc. where there is no browser.
- The DOM APIs do not sanitize the data. Hence it is possible to inject a script, thereby, opening our app an easy target for the XSS injection attack.
set-background.directive.ts:
import { Directive, ElementRef } from '@angular/core';
@Directive({
selector: '[appSetBackground]'
})
export class SetBackgroundDirective{
constructor(el: ElementRef) {
el.nativeElement.style.backgroundColor = "#00ff00"; // This will turn the background color of the attached element to green.
}
}
In the above code we written the code inside the constructor, that is not a good practice. so, instead of writing the code in constructor we can write it in ngOnInit method
import { Directive, ElementRef, OnInit } from '@angular/core';
@Directive({
selector: '[appSetBackground]'
})
export class SetBackgroundDirective implements OnInit {
constructor(private el: ElementRef) {
// el.nativeElement.style.backgroundColor = "#00ff00";
}
ngOnInit(){
this.el.nativeElement.style.backgroundColor = "#00ff00";
}
}
// Notice some changes
1. Implements OnInit interface for ngOnInit hook function
2. private el in the constructor, behind the scenes angular will create the private property with the name of el to be accessible throughout the class.
app.component.html:
<button appSetBackground>Click Me</button>
Using Renderer2 - It allows us to manipulate DOM without accessing the DOM elements directly. It provides a layer of abstraction between DOM element and component code.
set-background.directive.ts:
import { Directive, ElementRef, OnInit, Renderer2 } from '@angular/core';
@Directive({
selector: '[appSetBackground]'
})
export class SetBackgroundDirective implements OnInit {
constructor(private element: ElementRef, private renderer: Renderer2) { }
ngOnInit(){
this.renderer.setStyle(this.element.nativeElement, "backgroundColor", "#00ff00");
}
}
Step 3: Use the Directive
In your template, you can now use the appHighlight
attribute to apply the directive:
<button appSetBackground>Click Me</button>
Now, you would observe the background of the element would change to green.
Creating a Custom Attribute Directive Manually
Manually creating a custom attribute directive allows you to have a deeper understanding of how it works. Let's create the same appSetBackground
directive without using the Angular CLI:
Step 1: Create the Directive Files
Create a new TypeScript file for your directive, for example, set-background.directive.ts
, and define the directive class:
import { Directive, ElementRef, HostListener, Renderer2 } from '@angular/core';
@Directive({
selector: '[appSetBackground]'
})
export class SetBackgroundDirective {
constructor(private el: ElementRef, private renderer: Renderer2) { }
// same as above process
}
Step 2: Register the Directive
In your module file (e.g., app.module.ts
), import the SetBackgroundDirective
class and add it to the declarations
array:
import { SetBackgroundDirective } from './set-background.directive';
@NgModule({
declarations: [
// ... other components and directives
SetBackgroundDirective
],
// ...
})
export class AppModule { }
Step 3: Use the Directive
You can now use the appSetBackground
attribute to apply the directive in your template:
<p appHighlight>Hover over me!</p>