Loops
You will often need to display lists β such as recipes or ingredients. Angularβs @for block is the declarative way to do that.
Exampleβ
@for (recipe of recipes; track recipe.id) {
<mc-recipe-preview [recipe]="recipe" />
}
Angular has to track items to optimize DOM updates.
In opposition to the old *ngFor directive, the new @for block requires you to specify how to track each item.
If you want to track items by their index, because they don't have an id and reference equality is not enough, you can use the $index variable:
@for (ingredient of recipe.ingredients; track $index) {
<li>{{ ingredient }}</li>
}
Contextual Variablesβ
You will often need to display item numbers or use odd/even styles. That's why the @for block provides contextual variables:
$indexβ the current item's index,$firstβtrueif the current item is the first one,$lastβtrueif the current item is the last one,$evenβtrueif the current item's index is even,$oddβtrueif the current item's index is odd.
These variables can be used like this:
@for (step of recipe.steps; track $index) {
<li>#{{ $index + 1 }}. {{ step.description }}</li>
}
Empty Listsβ
@for supports @empty block to handle the case where the list is empty:
@for (step of recipe.steps; track $index) {
<li>#{{ $index + 1 }}. {{ step.description }}</li>
} @empty {
<p>No ingredients.</p>
}
@empty vs HTML SemanticsIn most cases, you will want to loop inside a container element, like ul or ol, while displaying the empty error message outside of it. In that case, prefer using an @if block instead of violating HTML semantics.
<ul>
@for (step of recipe.steps; track step.id) {
<li>#{{ $index + 1 }}. {{ step.description }}</li>
}
</ul>
@if (recipe.steps.length === 0) {
<p role="alert" aria-live="polite">No recipes found.</p>
}
