Angular Directives
Directives
Section titled “Directives”-
Fundamental building blocks that allow you to
manipulate the DOM. -
Directives add
new behaviorto existing elements ormodifytheirstructure. -
Every directive is marked with the
@Directive()decorator. -
There are
threemaintypesofdirectivesin Angular:Component DirectivesStructural DirectivesAttribute Directives
1. Component Directives
Section titled “1. Component Directives”-
A Component is a directive with a template, uses @Component decorator.
-
This is the
most common type of directiveyou’ll use. -
All Angular UI elements are built as components.
Component Example:
import { Component } from "@angular/core";
@Component({ selector: "app-user-card", // How you use it in HTML templateUrl: "./user-card.component.html", // Its dedicated template styleUrls: ["./user-card.component.css"],})export class UserCardComponent { // Component logic userName = "Jane Doe";}
// Used in template as<app-user-card></app-user-card>>2. Structural Directives
Section titled “2. Structural Directives”-
Structural Directives are responsible for
shaping or reshaping the DOM's structure -
Typically by
adding,removing, ormanipulatingelements. -
Built-in Structural Directives (
*ngIf,*ngFor,*ngSwitchor@if,@for,@switch)
Creating Custom Structural Directives
You can create a custom structural directive to implement reusable structural logic. This involves injecting two key classes:
TemplateRef: Represents the element’s content that the directive is attached to (the element without the directive’s attribute).ViewContainerRef: Represents the “anchor” location where you can embed the template.
Conceptual Process:
- Get the template content (
TemplateRef). - Decide where in the DOM to render it (
ViewContainerRef). - Use methods like
viewContainer.createEmbeddedView(templateRef)to show the element, or simply do nothing to hide/remove it.
Example (Simplified *ngUnless):
A custom directive that shows the element unless a condition is true (opposite of *ngIf).
import { Directive, Input, TemplateRef, ViewContainerRef } from "@angular/core";
@Directive({ selector: "[appUnless]" })export class UnlessDirective { private hasView = false;
// The setter runs whenever the input property changes @Input() set appUnless(condition: boolean) { if (!condition && !this.hasView) { // Create the view (show the element) this.viewContainer.createEmbeddedView(this.templateRef); this.hasView = true; } else if (condition && this.hasView) { // Clear the view (remove the element) this.viewContainer.clear(); this.hasView = false; } }
constructor( private templateRef: TemplateRef<any>, private viewContainer: ViewContainerRef ) {}}Usage: <div *appUnless="isValid">This will show if isValid is false.</div>
3. Attribute Directives
Section titled “3. Attribute Directives”-
Attribute Directives are responsible for
changing the appearance or behavior of an element, component, or another directiveby modifying its properties. -
They
do not add or remove elementsfrom theDOM. -
Built-in Attribute Directives (
[ngClass],[ngStyle],ngModel)
Creating Custom Attribute Directives
You create a custom attribute directive using the @Directive() decorator and typically inject the ElementRef and optionally Renderer2 services.
ElementRef: Gives you direct access to the host DOM element, allowing you to manipulate it.Renderer2: The preferred, safer way to manipulate the DOM, as it abstracts away direct DOM access, which can be useful when Angular is running in a non-browser environment (like server-side rendering).
Example (Simplified appHighlight):
A custom directive that highlights the element it is attached to.
import { Directive, ElementRef, HostListener, Input, Renderer2,} from "@angular/core";
@Directive({ selector: "[appHighlight]", // Used as an attribute on an element})export class HighlightDirective { // Input property to allow setting a custom highlight color @Input() highlightColor: string = "yellow";
constructor(private el: ElementRef, private renderer: Renderer2) { // You could also apply the style here, but using HostListener is more common for interactive changes. }
// Use @HostListener to react to events on the host element @HostListener("mouseenter") onMouseEnter() { this.changeColor(this.highlightColor); }
@HostListener("mouseleave") onMouseLeave() { this.changeColor(null); }
private changeColor(color: string | null) { // Renderer2 is the recommended way to manipulate the DOM this.renderer.setStyle(this.el.nativeElement, "background-color", color); }}Usage:
- Using the default color:
<p appHighlight>Highlight me</p> - Using a custom color:
<p appHighlight [highlightColor]="'green'">Highlight me green</p>