← Back to Tutorials Chapter 4

Directives

What Are Directives?

Directives are classes that add behavior to elements in your Angular templates. There are three categories: components (directives with a template), attribute directives (change appearance or behavior of an element), and structural directives (change the DOM layout by adding or removing elements).

Attribute Directives

Attribute directives modify the appearance or behavior of an element. Angular provides built-in attribute directives and you can create custom ones.

ngClass

Add or remove multiple CSS classes dynamically:

<div [ngClass]="{
  'highlight': isHighlighted,
  'error': hasError,
  'disabled': isDisabled
}">Conditional classes</div>

ngStyle

Set multiple inline styles dynamically:

<div [ngStyle]="{
  'color': textColor,
  'font-size': fontSize + 'px',
  'background': bgColor
}">Dynamic styles</div>

Custom Attribute Directive

Create a custom directive using the @Directive decorator:

import { Directive, ElementRef, Renderer2, HostListener, HostBinding } from '@angular/core';

@Directive({
  selector: '[appHighlight]'
})
export class HighlightDirective {
  @HostBinding('style.backgroundColor') bgColor = 'transparent';

  constructor(private el: ElementRef, private renderer: Renderer2) { }

  @HostListener('mouseenter') onMouseEnter() {
    this.bgColor = 'yellow';
    this.renderer.setStyle(this.el.nativeElement, 'fontWeight', 'bold');
  }

  @HostListener('mouseleave') onMouseLeave() {
    this.bgColor = 'transparent';
    this.renderer.setStyle(this.el.nativeElement, 'fontWeight', 'normal');
  }
}

Use it in templates: <p appHighlight>Hover over me!</p>.

ElementRef gives access to the native DOM element. Renderer2 is the preferred API for modifying the DOM because it works in both browser and server environments. @HostListener listens to events on the host element. @HostBinding binds a class or property on the host element.

Structural Directives

Structural directives change the structure of the DOM by adding, removing, or manipulating elements. They are prefixed with an asterisk * in templates, which is syntactic sugar for an <ng-template> wrapper.

ngIf

Conditionally include a template based on a boolean expression:

<div *ngIf="isLoggedIn; else loginPrompt">
  Welcome, {{ username }}!
</div>
<ng-template #loginPrompt>
  <p>Please log in.</p>
</ng-template>

ngFor

Iterate over a collection and render a template for each item:

<ul>
  <li *ngFor="let user of users; let i = index; trackBy: trackByUserId">
    {{ i + 1 }}. {{ user.name }}
  </li>
</ul>

Local variables available: index, first, last, even, odd, count.

Always use trackBy with ngFor when working with large lists. It helps Angular identify which items changed, improving rendering performance by avoiding unnecessary DOM manipulations.

ngSwitch

Switch between multiple conditional templates:

<div [ngSwitch]="role">
  <p *ngSwitchCase="'admin'">Admin Panel</p>
  <p *ngSwitchCase="'editor'">Content Editor</p>
  <p *ngSwitchCase="'viewer'">Read Only</p>
  <p *ngSwitchDefault>Unknown role</p>
</div>

Custom Structural Directive

Create your own structural directive using TemplateRef and ViewContainerRef:

import { Directive, Input, TemplateRef, ViewContainerRef } from '@angular/core';

@Directive({
  selector: '[appRepeat]'
})
export class RepeatDirective {
  constructor(
    private templateRef: TemplateRef<any>,
    private viewContainer: ViewContainerRef
  ) { }

  @Input() set appRepeat(times: number) {
    this.viewContainer.clear();
    for (let i = 0; i < times; i++) {
      this.viewContainer.createEmbeddedView(this.templateRef);
    }
  }
}

Usage: <p *appRepeat="5">Repeated paragraph</p>.

Microsyntax

Structural directives use microsyntax — a compact language for expressing template logic. The *ngFor="let item of items; let i = index" is shorthand that Angular desugars into <ng-template ngFor let-item="$implicit" [ngForOf]="items" let-i="index">.

Angular directives overview

Summary

This chapter covered attribute directives (ngClass, ngStyle, custom) and structural directives (ngIf, ngFor, ngSwitch, custom). You learned how to use ElementRef, Renderer2, @HostListener, @HostBinding, TemplateRef, ViewContainerRef, and microsyntax to build powerful, reusable behavior.

Exercise 4: Build a custom attribute directive appTooltip that shows a tooltip on hover with a configurable text and position (top, bottom, left, right). Include a fade-in animation using Renderer2. Then build a custom structural directive appPermission that conditionally renders content based on a user role string input.