Angular templates support control flow blocks that let you conditionally show, hide, and repeat elements.
@if block conditionals
The @if block conditionally displays its content when its condition expression is truthy:
@if (a > b) { {{a}} is greater than {{b}}}
The @if block might have one or more associated @else blocks. Immediately after an @if block, you can optionally
specify any number of @else if blocks and one @else block:
@if (a > b) { {{a}} is greater than {{b}}} @else if (b > a) { {{a}} is less than {{b}}} @else { {{a}} is equal to {{b}}}
Referencing the conditional expression's result
The new built-in @if conditional supports referencing of expression results to keep a solution for common coding
patterns:
@if (users$ | async; as users) { {{ users.length }}}
@for block - repeaters
The @for repeatedly renders content of a block for each item in a collection. The collection can be represented as any
JavaScript iterable but there
are performance advantages of using a regular Array. A basic @for loop looks like:
@for (item of items; track item.id) { {{ item.name }}}
track for calculating difference of two collections
The value of the track expression determines a key used to associate array items with the views in the DOM. Having
clear indication of the item identity allows Angular to execute a minimal set of DOM operations as items are added,
removed or moved in a collection.
Using track effectively can significantly enhance your application's performance, especially in loops over data collections.
For collections that do not undergo modifications (no items are moved, added, or deleted), using track $index is an
efficient strategy. For collections with mutable data or frequent changes, select a property that uniquely identifies
each item to use as your track expression.
Be aware of the potential for increased DOM re-creation when using object identity as a track key with immutable data structures, as this can lead to unnecessary performance costs.
$index and other contextual variables
Inside @for contents, several implicit variables are always available:
| Variable | Meaning |
|---|---|
$count |
Number of items in a collection iterated over |
$index |
Index of the current row |
$first |
Whether the current row is the first row |
$last |
Whether the current row is the last row |
$even |
Whether the current row index is even |
$odd |
Whether the current row index is odd |
These variables are always available with these names, but can be aliased via a let segment:
@for (item of items; track item.id; let idx = $index, e = $even) {Item #{{ idx }}: {{ item.name }}}
The aliasing is especially useful in case of using nested @for blocks where contextual variable names could collide.
empty block
You can optionally include an @empty section immediately after the @for block content. The content of the @empty
block displays when there are no items:
@for (item of items; track item.name) { <li> {{ item.name }}</li>} @empty { <li> There are no items.</li>}
@switch block - selection
The syntax for switch is very similar to if, and is inspired by the JavaScript switch statement:
@switch (condition) { @case (caseA) { Case A. } @case (caseB) { Case B. } @default { Default case. }}
The value of the conditional expression is compared to the case expression using the === operator.
@switch does not have fallthrough, so you do not need an equivalent to a break or return statement.
The @default block is optional and can be omitted. If no @case matches the expression and there is no @default
block, nothing is shown.
Built-in control flow and the NgIf, NgSwitch and NgFor structural directives
The @if block replaces *ngIf for expressing conditional parts of the UI.
The @switch block replaces ngSwitch with major benefits:
- it does not require a container element to hold the condition expression or each conditional template;
- it supports template type-checking, including type narrowing within each branch.
The @for block replaces *ngFor for iteration, and has several differences compared to its structural
directive NgFor predecessor:
- tracking expression (calculating keys corresponding to object identities) is mandatory but has better ergonomics (it
is enough to write an expression instead of creating the
trackBymethod); - uses a new optimized algorithm for calculating a minimal number of DOM operations to be performed in response to
changes in a collection, instead of Angular’s customizable diffing implementation (
IterableDiffer); - has support for
@emptyblocks.
The track setting replaces NgFor's concept of a trackBy function. Because @for is built-in, we can provide a
better experience than passing a trackBy function, and directly use an expression representing the key instead.
Migrating from trackBy to track is possible by invoking the trackBy function:
@for (item of items; track itemId($index, item)) { {{ item.name }}}