Chapter 3: Control Flow (@if, @for, @switch)

Control Flow (@if, @for, @switch) — this is where Angular templates start feeling modern, clean, and way less cluttered compared to the old *ngIf, *ngFor, *ngSwitch days.

Think of the old way like writing emails with lots of attachments and footnotes. The new way (@if / @for / @switch) is like writing clean, readable prose — everything is right there in the template, no extra wrappers, no asterisks everywhere, and it plays beautifully with signals for automatic reactivity.

Introduced in Angular 17 (2023), stabilized and improved through 18–19–21+, this is now the recommended way in 2026. Almost all new code and tutorials use it.

Why the new syntax? (Quick teacher rant)

Old structural directives (*ngIf etc.):

  • Required an extra <ng-template> for else/then
  • Created hidden wrapper elements sometimes
  • Harder to read nested conditions
  • Less type narrowing in branches
  • Change detection was zone.js-heavy

New block syntax:

  • No directives → built into the template parser
  • Cleaner, more JS-like
  • Better performance (especially with track + signals)
  • Full signal reactivity → change a signal → only the affected block updates
  • Easier migration tools exist (ng update)

1. @if + @else if + @else (Conditional rendering)

Replaces *ngIf.

Basic syntax

HTML

With else

HTML

Chained else if (multiple branches)

HTML

Alias with as (super useful for observables/signals)

HTML

→ Saves you from writing user()?.name everywhere inside the block.

Reactivity with signals

TypeScript
HTML

→ Because showMessage() is a signal read, Angular knows exactly when to re-evaluate this block.

2. @for + @empty (Looping / Repeating)

Replaces *ngFor.

Basic syntaxtrack is mandatory (and the most important part!)

HTML

Why track?

  • Tells Angular how to identify items between renders
  • Prevents unnecessary DOM destroy/create → huge perf win
  • Best: use unique ID (id, _id, uuid)
  • Okay: $index (if list never reorders)
  • Avoid: track item (object reference) unless list is immutable/static

@empty block (replaces showing “no items” manually)

HTML

Context variables (like let-i = index in old ngFor)

Built-in: $index, $first, $last, $even, $odd, $count

HTML

Aliasing outer variables in nested loops

HTML

3. @switch + @case + @default (Multi-way branching)

Replaces *ngSwitch.

Great when you have one value with many possible states (user role, order status, theme, etc.).

Syntax

HTML
  • Uses strict === comparison
  • No fallthrough (no need for break)
  • @default is optional — if no match and no default → nothing renders

With signals

TypeScript
HTML

Quick Comparison Table (Old vs New)

Feature Old (*ngIf / *ngFor / *ngSwitch) New (@if / @for / @switch)
Syntax *ngIf=”…” on element Block @if { … }
Else Needs <ng-template #else> Just @else { … }
Empty list Manual *ngIf=”!items?.length” Built-in @empty { … }
Tracking trackBy function Inline track expr (simpler & faster)
Nested readability Lots of nesting & wrappers Clean, indented blocks
Signal integration Works, but Zone.js Native, fine-grained reactivity
Imports needed? CommonModule Nothing — built-in

Mini Practice Task (try this in your app!)

In your app.component.ts, add these signals:

TypeScript

Then in template:

HTML

Play with adding items, changing filter — watch how smoothly it updates.

This chapter unlocks 80% of what makes Angular templates feel modern in 2026.

Next up is usually outputs & events (child talking back to parent) — or do you want to deepen any part here (track gotchas, migration tips, nested examples)? Just say the word! 😊

You may also like...

Leave a Reply

Your email address will not be published. Required fields are marked *