Directives add behavior to DOM elements. Angular provides built-in directives for common patterns and lets you write custom ones.

Structural Directives

Structural directives change the DOM layout by adding or removing elements.

*ngIf — Conditional Rendering

  import { Component } from '@angular/core';
import { NgIf } from '@angular/common';

@Component({
  selector: 'app-auth-message',
  standalone: true,
  imports: [NgIf],
  template: `
    <p *ngIf="isLoggedIn">Welcome back!</p>
    <p *ngIf="!isLoggedIn">Please log in.</p>
  `
})
export class AuthMessageComponent {
  isLoggedIn = false;
}
  

Modern control flow syntax (Angular 17+):

  @if (isLoggedIn) {
  <p>Welcome back!</p>
} @else {
  <p>Please log in.</p>
}
  

*ngFor — Lists

  import { NgFor } from '@angular/common';

@Component({
  selector: 'app-todo-list',
  standalone: true,
  imports: [NgFor],
  template: `
    <ul>
      <li *ngFor="let todo of todos; let i = index; trackBy: trackById">
        {{ i + 1 }}. {{ todo.text }}
      </li>
    </ul>
  `
})
export class TodoListComponent {
  todos = [
    { id: 1, text: 'Learn directives' },
    { id: 2, text: 'Build a component' }
  ];

  trackById(_index: number, todo: { id: number }) {
    return todo.id;
  }
}
  

Modern syntax:

  @for (todo of todos; track todo.id) {
  <li>{{ todo.text }}</li>
}
  

Always use trackBy or track to help Angular identify list items efficiently.

Attribute Directives

Attribute directives change the appearance or behavior of an existing element.

ngClass — Dynamic CSS Classes

  import { NgClass } from '@angular/common';

@Component({
  selector: 'app-status-badge',
  standalone: true,
  imports: [NgClass],
  template: `
    <span [ngClass]="{
      'badge-success': status === 'active',
      'badge-warning': status === 'pending',
      'badge-error': status === 'failed'
    }">{{ status }}</span>
  `
})
export class StatusBadgeComponent {
  status: 'active' | 'pending' | 'failed' = 'active';
}
  

Object syntax maps class names to boolean expressions. Array syntax applies multiple classes:

  <div [ngClass]="['card', isHighlighted ? 'highlight' : '']">Content</div>
  

ngStyle — Inline Styles

  import { NgStyle } from '@angular/common';

@Component({
  selector: 'app-progress-bar',
  standalone: true,
  imports: [NgStyle],
  template: `
    <div class="bar" [ngStyle]="{ width: percent + '%', background: color }"></div>
  `
})
export class ProgressBarComponent {
  percent = 75;
  color = '#28a745';
}
  

Prefer CSS classes over inline styles when possible for maintainability.

Directives keep templates declarative — express what to show and how it should look based on your data.