In Angular, directives are used to add behavior to DOM elements, either by modifying the DOM directly or by adding functionality to an element in the template. Directives are key to creating dynamic, interactive web applications. Understanding directives is essential for Angular developers, as they help enhance your UI and improve code maintainability.
What Are Angular Directives?
Directives are classes in Angular that allow you to extend HTML functionality. They can:
Modify the DOM – Change the structure, style, or behavior of the element.
Add behavior to DOM elements – Like handling events, controlling data, and more.
Angular provides three types of directives:
Structural Directives: Change the layout of the DOM by adding or removing elements.
Attribute Directives: Change the appearance or behavior of an element.
Component Directives: Technically, components are also a form of directive (they use templates, but are more complex, containing both a view and logic).
Types of Directives in Angular
Structural Directives: These directives alter the structure of the DOM by adding, removing, or manipulating elements.
- Examples:
*ngIf
,*ngFor
,ngSwitch
, etc.
- Examples:
Attribute Directives: These directives modify the appearance or behavior of an existing DOM element.
- Examples:
ngClass
,ngStyle
,ngModel
, etc.
- Examples:
Component Directives: These are directives with templates. Technically, every component is a directive with a template.
- Example:
app-header
,app-footer
(custom components).
- Example:
1. Structural Directives
Structural directives are responsible for altering the structure of the DOM. They work by adding or removing elements based on conditions or loops.
Example: *ngIf
*ngIf
is used to conditionally include or remove an element from the DOM.
Example Usage:
htmlCopy code<div *ngIf="isVisible">
<h2>Welcome to Angular!</h2>
</div>
Component Class (TypeScript):
typescriptCopy codeimport { Component } from '@angular/core';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
isVisible = true; // Control the visibility of the element
}
In this example, the <h2>
element is only displayed if isVisible
is true
. If it is false
, the element is removed from the DOM.
Example: *ngFor
*ngFor
is used to loop through a list and repeat the same DOM structure for each item.
Example Usage:
htmlCopy code<ul>
<li *ngFor="let item of items">{{ item }}</li>
</ul>
Component Class (TypeScript):
typescriptCopy codeimport { Component } from '@angular/core';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
items = ['Item 1', 'Item 2', 'Item 3'];
}
In this case, Angular will generate an <li>
element for each item in the items
array.
2. Attribute Directives
Attribute directives change the appearance or behavior of an existing DOM element. They do not change the structure of the DOM but modify the element to which they are applied.
Example: ngClass
The ngClass
directive is used to add or remove CSS classes based on conditions.
Example Usage:
htmlCopy code<div [ngClass]="{ 'active': isActive, 'inactive': !isActive }">
<h2>Directive Example</h2>
</div>
Component Class (TypeScript):
typescriptCopy codeimport { Component } from '@angular/core';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
isActive = true;
}
Here, the class active
will be applied to the <div>
if isActive
is true
, and inactive
will be applied if it is false
.
Example: ngStyle
The ngStyle
directive allows you to dynamically set inline styles.
Example Usage:
htmlCopy code<div [ngStyle]="{ 'color': isActive ? 'green' : 'red' }">
<h2>Style Directive Example</h2>
</div>
Component Class (TypeScript):
typescriptCopy codeimport { Component } from '@angular/core';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
isActive = true; // If true, the color will be green, otherwise red
}
In this case, the color of the text will be green
if isActive
is true
, and red
if it is false
.
3. Custom Directives
You can also create your own custom directives to modify the behavior of DOM elements.
Example: Custom Attribute Directive
Let’s say we want to create a custom directive that changes the background color of an element when the user hovers over it.
Step 1: Create the Directive
typescriptCopy codeimport { Directive, ElementRef, HostListener } from '@angular/core';
@Directive({
selector: '[appHoverColor]' // Custom selector to apply the directive
})
export class HoverColorDirective {
constructor(private el: ElementRef) { }
@HostListener('mouseenter') onMouseEnter() {
this.changeColor('yellow'); // Change color on hover
}
@HostListener('mouseleave') onMouseLeave() {
this.changeColor('white'); // Revert color when hover ends
}
private changeColor(color: string) {
this.el.nativeElement.style.backgroundColor = color;
}
}
Step 2: Use the Custom Directive in a Template
htmlCopy code<div appHoverColor>
Hover over this text to change its background color!
</div>
Here, the appHoverColor
directive is applied to the <div>
, changing the background color when the user hovers over it.
Explanation:
ElementRef
gives direct access to the DOM element that the directive is attached to.HostListener
listens for events like mouse enter or mouse leave and applies the desired functionality.@Directive
defines a custom attribute directive, which modifies the element’s behavior.
Advanced Concepts in Angular Directives
1. Structural Directives with Local Variables
In addition to adding or removing elements, structural directives like *ngIf
and *ngFor
can create local variables that provide additional context.
For example, *ngFor
creates a local variable for each iteration, such as index
or odd/even
.
htmlCopy code<ul>
<li *ngFor="let item of items; let i = index">
{{ i + 1 }}. {{ item }}
</li>
</ul>
Here, i
will give the index of each item.
2. Dynamic Directive Creation
You can also dynamically create directives at runtime using the ComponentFactoryResolver
and ViewContainerRef
in Angular. This is an advanced use case but enables the loading of components or directives dynamically based on user interaction or other events.
3. Directive Lifecycle Hooks
Angular also provides lifecycle hooks for directives, such as:
ngOnInit(): Called when the directive is initialized.
ngOnDestroy(): Called when the directive is destroyed.
For instance, you could handle cleanup in ngOnDestroy
when dealing with custom event listeners in directives.
typescriptCopy codeimport { Directive, OnDestroy } from '@angular/core';
@Directive({
selector: '[appCustomDirective]'
})
export class CustomDirective implements OnDestroy {
ngOnDestroy() {
console.log('Directive destroyed');
}
}
Conclusion:
Directives are fundamental to building interactive UIs in Angular. They allow you to manipulate the DOM, add behaviors, and enhance user interaction.
There are three types of directives: Structural, Attribute, and Component Directives.
Custom directives provide a powerful way to extend Angular’s capabilities.
Advanced topics such as directive lifecycle hooks and dynamic directive creation allow you to build highly dynamic and efficient Angular applications.