Angular templates support control flow blocks that let you conditionally show, hide, and repeat elements.
Note: This was previously accomplished with the *ngIf, *ngFor, and *ngSwitch directives.
Conditionally display content with @if
, @else-if
and @else
The @if
block conditionally displays its content when its condition expression is truthy:
@if (a > b) { <p>{{a}} is greater than {{b}}</p>}
If you want to display alternative content, you can do so by providing any number of @else if
blocks and a singular @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 @if
conditional supports saving the result of the conditional expression into a variable for reuse inside of the block.
@if (user.profile.settings.startDate; as startDate) { {{ startDate }}}
This can be useful for referencing longer expressions that would be easier to read and maintain within the template.
Repeat content with the @for
block
The @for
block loops through a collection and repeatedly renders the content of a block. The collection can be any JavaScript iterable, but Angular has additional performance optimizations for Array
values.
A typical @for
loop looks like:
@for (item of items; track item.id) { {{ item.name }}}
Why is track
in @for
blocks important?
The track
expression allows Angular to maintain a relationship between your data and the DOM nodes on the page. This allows Angular to optimize performance by executing the minimum necessary DOM operations when the data changes.
Using track effectively can significantly improve your application's rendering performance when looping over data collections.
Select a property that uniquely identifies each item in the track
expression. If your data model includes a uniquely identifying property, commonly id
or uuid
, use this value. If your data does not include a field like this, strongly consider adding one.
For static collections that never change, you can use $index
to tell Angular to track each item by its index in the collection.
If no other option is available, you can specify identity
. This tells Angular to track the item by its reference identity using the triple-equals operator (===
). Avoid this option whenever possible as it can lead to significantly slower rendering updates, as Angular has no way to map which data item corresponds to which DOM nodes.
Contextual variables in @for
blocks
Inside @for
blocks, 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) { <p>Item #{{ idx }}: {{ item.name }}</p>}
The aliasing is useful when nesting @for
blocks, letting you read variables from the outer @for
block from an inner @for
block.
Providing a fallback for @for
blocks with the @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 aria-hidden="true"> There are no items. </li>}
Conditionally display content with the @switch
block
While the @if
block is great for most scenarios, the @switch
block provides an alternate syntax to conditionally render data. Its syntax closely resembles JavaScript's switch
statement.
@switch (userPermissions) { @case ('admin') { <app-admin-dashboard /> } @case ('reviewer') { <app-reviewer-dashboard /> } @case ('editor') { <app-editor-dashboard /> } @default { <app-viewer-dashboard /> }}
The value of the conditional expression is compared to the case expression using the triple-equals (===
) operator.
@switch
does not have a fallthrough, so you do not need an equivalent to a break
or return
statement in the block.
You can optionally include a @default
block. The content of the @default
block displays if none of the preceding case expressions match the switch value.
If no @case
matches the expression and there is no @default
block, nothing is shown.