New Control Flow
New Control Flow
Section titled โNew Control Flowโ@if (items.length) { <li @for (item of items; track item.id)>{{ item.name }}</li>}Notes
- Replaces many structural directive use cases with built-ins.
Before vs After
Section titled โBefore vs AfterโBefore (Angular โค v16 โ structural directives)
Section titled โBefore (Angular โค v16 โ structural directives)โ<!-- *ngIf with else template --><div *ngIf="items?.length; else empty"> <ul> <li *ngFor="let item of items; trackBy: trackById">{{ item.name }}</li> </ul></div><ng-template #empty> <p>No items</p></ng-template>trackById(index: number, item: { id: number }) { return item.id; }After (Angular v17+ โ new control flow)
Section titled โAfter (Angular v17+ โ new control flow)โ@if (items?.length > 0) { <ul> @for (item of items; track item.id) { <li>{{ item.name }}</li> } </ul>} @else { <p>No items</p>}Async values (before/after)
Section titled โAsync values (before/after)โ<div *ngIf="user$ | async as user; else loading"> Hello {{ user.name }}</div><ng-template #loading>Loadingโฆ</ng-template>@if (user$ | async; as user) { Hello {{ user.name }}} @else { Loadingโฆ}Else-if chain
Section titled โElse-if chainโ@if (status === 'loading') { <p>Loadingโฆ</p>} @else if (status === 'error') { <p>Something went wrong.</p>} @else { <p>Ready!</p>}Pitfalls
Section titled โPitfallsโ- Always provide a stable key with
trackin@for(e.g.,track item.id) to avoid DOM churn. - Donโt mix old structural directives (
*ngIf,*ngFor) with new syntax on the same element; wrap or nest instead. - The
asbinding (e.g.,@if (expr; as value)) is block-scoped; it isnโt visible outside the@ifblock. - Use parentheses for complex conditions to keep expressions clear and avoid precedence surprises.
- Avoid non-deterministic expressions (like
Math.random()/Date.now()) inside control flow when doing SSR to prevent hydration mismatches.