codejump

AcademyAngular

Control Flow: @if and @for

Angular 17+ replaced *ngIf and *ngFor with built-in @if and @for blocks — faster, stricter about tracking, and no CommonModule import required.

2 min readUpdated

3 exercises

Waiting at the end of this page.

@if replaces *ngIf, with a real else branch

The new block syntax is a template primitive, not a structural directive, so it needs no * prefix and no CommonModule import:

HTML
@if (status === 'success') {
  <span class="badge badge-ok">Ready</span>
} @else if (status === 'error') {
  <span class="badge badge-error">Failed</span>
} @else {
  <span class="badge badge-pending">Pending</span>
}

A three-state badge like this used to need either a nested *ngIf/else chain or an [ngSwitch]; @if/@else if/@else reads as what it is, and the compiler enforces that branches are mutually exclusive.

@for requires track, and track is not optional styling

@for replaces *ngFor, and its track expression is mandatory — omitting it is a compile error, not a lint warning:

HTML
@for (todo of visibleTodos; track todo.id) {
  <li [class.done]="todo.done">{{ todo.text }}</li>
} @empty {
  <li class="empty">Nothing matches.</li>
}

track tells Angular which DOM node maps to which data item across re-renders. Tracking by todo.id means reordering the array reorders the existing <li> elements; tracking by $index (or forgetting a stable key entirely, the way *ngFor let you) means Angular matches by position instead of identity, so filtering the list drops and recreates elements it should have kept — and if one of those elements owns focus, as a search input does, position-based tracking loses that focus on every keystroke because a "different" element now occupies the same slot.

@switch replaces ngSwitch the same way

@switch (value) { @case (a) {...} @case (b) {...} @default {...} } mirrors @if's improvements over its structural-directive predecessor for the same reason: it is parsed at compile time, so a typo in a @case value is caught before runtime rather than silently matching nothing.

What interviewers check

Whether you reach for @if/@for by default in anything Angular 17+, whether you can explain why track exists and what breaks without a stable one, and whether you have actually hit the "state disappears while typing" bug that a wrong track expression produces — it is the single most common Angular list bug in production code, not just a textbook warning.

Now practice it

1 quiz · 2 drills

Reading this page is the cheap half. These are the exercises that make you use it.