Roadmap › Angular (2 → 21) › Module: Getting Started
Lessons in this course (16)

3. Built-in control flow, directives and pipes

Basic★ Must knowLesson 3 of 16
html
@if (orders().length > 0) {
  <ul>
    @for (o of orders(); track o.id; let i = $index) {
      <li>{{ i + 1 }}. {{ o.customer }} — {{ o.total | currency:'INR' }}</li>
    } @empty {
      <li>No orders</li>
    }
  </ul>
} @else {
  <p>Loading…</p>
}

@switch (status()) {
  @case ('paid') { <span class="ok">Paid</span> }
  @default { <span>Pending</span> }
}

@defer (on viewport) { <app-sales-chart /> } @placeholder { <p>Chart loads when visible</p> }
@let total = order().qty * order().price;

Legacy structural directives (deprecated in v20, still common in existing code): *ngIf="cond; else loading", *ngFor="let o of orders; trackBy: trackById", [ngSwitch]. Attribute directives: [ngClass], [ngStyle], [(ngModel)].

Pipes transform values in templates: date, currency, number, percent, uppercase, lowercase, titlecase, json, slice, keyvalue, async (subscribes to an Observable/Promise and unsubscribes automatically). Pipes are pure by default (re-run only when inputs change).

ts
@Pipe({ name: "statusLabel" })
export class StatusLabelPipe implements PipeTransform {
  transform(status: string): string { return { paid: "Paid", pending: "Pending" }[status] ?? status; }
}