Mastering Angular Directives: Enhance Your HTML with Custom Behaviours
Charity Darko
Full-Stack Software Engineer ?????? | Angular, PHP, Python | Passionate About Design & Exploring iOS Development | Inspiring & Leading High-Performing Teams
Ready to take your development further? Directives are the secret sauce to making elements smarter, reusable, and more dynamic!—making your components efficient!
With directives, you can modify the DOM, create interactive components, and apply logic effortlessly—all while keeping your code clean and modular.
In this article, we’ll break down the three types of Angular directives, explore when to use them, and dive into a real-world example of a custom directive that takes UI interactions to the next level.
Types of Angular Directives
- Component Directives – These are custom UI elements (technically directives with a template) that help in building reusable components.
- Structural Directives (e.g., *ngIf, *ngFor) – These directives modify the DOM structure dynamically based on conditions.
- Attribute Directives (e.g., [ngClass], [ngStyle]) – These are used to alter the appearance or behavior of an element.
When to Use Directives?
Directives come in handy when:
- You need reusable behaviors across multiple components.
- You want to extend the behavior of existing elements without modifying their internal code.
- You need DOM manipulation that doesn’t fit inside a component.
Practical Example: Building an Expandable Food Directory Using an Attribute Directive
To illustrate the power of directives, let’s create a custom directive, appDirectoryView, that allows users to expand and collapse sections of a food directory.
领英推è
Component Data (directive-view.component.ts)
import { Component } from '@angular/core';
@Component({
selector: 'app-food-directory',
templateUrl: './food-directory.component.html',
styleUrls: ['./food-directory.component.css']
})
export class FoodDirectoryComponent {
foodDirectories = [
{
name: 'Bratwurst (German Sausage)',
flag: '????',
ingredients: ['?? Pork', '?? Nutmeg', '?? Garlic', '?? Salt', '??? White Pepper']
},
{
name: 'Jollof Rice (Ghanaian Rice Dish)',
flag: '????',
ingredients: ['?? Rice', '?? Tomatoes', '?? Onions', '??? Chili Peppers', '?? Chicken']
},
{
name: 'Sauerbraten (German Pot Roast)',
flag: '????',
ingredients: ['?? Beef', '?? Vinegar', '?? Bay Leaves', '?? Carrots', '?? Onions']
},
{
name: 'Fufu & Light Soup (Ghanaian Dish)',
flag: '????',
ingredients: ['?? Plantains', '?? Cassava', '?? Tomatoes', '?? Goat Meat', '?? Basil']
}
];
}
Directive File (directory-view.directive.ts)
import { Directive, ElementRef, HostListener, Input, Renderer2 } from '@angular/core';
@Directive({
selector: '[appDirectoryView]'
})
export class DirectoryViewDirective {
@Input() collapsedColor: string = 'lightgray';
@Input() expandedColor: string = 'lightblue';
private isExpanded: boolean = false;
constructor(private el: ElementRef, private renderer: Renderer2) {
this.setBackground(this.collapsedColor);
}
@HostListener('click', ['$event']) toggleDirectory(event: Event) {
event.stopPropagation();
this.isExpanded = !this.isExpanded;
const displayStyle = this.isExpanded ? 'block' : 'none';
const backgroundColor = this.isExpanded ? this.expandedColor : this.collapsedColor;
this.setBackground(backgroundColor);
const children = this.el.nativeElement.querySelectorAll('.directory-item');
children.forEach((child: HTMLElement) => {
this.renderer.setStyle(child, 'display', displayStyle);
});
}
private setBackground(color: string) {
this.renderer.setStyle(this.el.nativeElement, 'background-color', color);
this.renderer.setStyle(this.el.nativeElement, 'cursor', 'pointer');
this.renderer.setStyle(this.el.nativeElement, 'padding', '8px');
this.renderer.setStyle(this.el.nativeElement, 'border-radius', '5px');
this.renderer.setStyle(this.el.nativeElement, 'margin', '4px 0');
}
}
Component Template (directive-view.component.html)
<div style="padding: 14rem; width: 1000px;">
<div *ngFor="let food of foodDirectories"
appDirectoryView
collapsedColor="lightgray"
expandedColor="lightblue">
{{ food.flag }} ?? {{ food.name }}
<div *ngFor="let ingredient of food.ingredients"
class="directory-item"
appDirectoryView
collapsedColor="white"
expandedColor="lightyellow">
{{ ingredient }}
</div>
</div>
</div>
How It Works
- Clicking on a food category expands/collapses its ingredients.
- The directive dynamically changes background color based on state.
- Uses Angular’s Renderer2 to modify the DOM safely.
Conclusion
Wow! you came this far! send me a dm ?
JSYK: Directives are a core part of Angular’s flexibility, allowing developers to enhance HTML elements with custom behaviors. Whether you’re modifying appearance with attribute directives, changing the DOM structure using structural directives, or creating reusable component directives, mastering them will significantly improve your Angular applications