What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
Use Angular’s @for block to render one template instance for each item in a collection. Every loop needs a track expression: choose a unique, stable item property such as item.id for a changing list, or $index when the list is static. Add @empty after the loop content when you want a message for a collection with no items.
Write a basic @for loop
The general form is @for (item of items; track item.id) { ... }. Angular renders the block for each value in the iterable. For example:
As an Amazon Associate I earn from qualifying purchases.
<ul>
@for (item of items; track item.id) {
<li>{{ item.name }}</li>
}
</ul>
Here, items is the collection, item is the current value, and item.name is rendered for that value. The Angular @for API accepts JavaScript iterables; arrays receive additional performance optimizations.
Choose a tracking expression that fits the collection
The required track expression connects each data item with its rendered DOM view. That lets Angular identify which views to keep, update, or move as the collection changes, limiting unnecessary DOM operations. Angular’s control-flow guide recommends a unique property for collections that may change.
#1 Best Overall
| Tracking expression | Best fit | What to consider |
|---|---|---|
track item.id |
A collection whose membership or order can change | Use a property that uniquely identifies each item and remains stable across updates. Duplicate or changing keys do not reliably identify rows. |
track $index |
A collection that is truly static | Indexes identify positions, not item identities. If items are inserted, removed, or reordered, a position can refer to a different item. |
track item |
Generally avoid for changing collections | Tracking by object reference can make updates significantly slower because Angular cannot map items to DOM nodes as directly. |
For example, if a server refreshes a list with new object instances representing the same records, a stable identifier such as item.id allows Angular to associate the records with their existing views. Do not use an identifier that can collide between items or change during the item’s lifetime.
There is a migration behavior worth checking when the tracked property itself changes. If the object reference stays the same, Angular updates bindings, including component inputs, rather than destroying and recreating the element. Angular documents this as a difference from *ngFor in the corresponding case; see the @for API.
Rank #2
Show an empty state with @empty
Place @empty immediately after the loop’s closing brace. Its content is rendered when the collection has no items:
<ul>
@for (item of items; track item.id) {
<li>{{ item.name }}</li>
} @empty {
<li>No items are available.</li>
}
</ul>
This keeps the no-results message alongside the loop that determines whether it should appear. It is useful for empty search results, an initially empty list, or a collection with no available records.
Rank #3
Use the loop’s contextual variables
Inside the block, Angular provides $count, $index, $first, $last, $even, and $odd. Alias a value in the let segment when you want a shorter or clearer name:
@for (item of items; track item.id; let i = $index, last = $last) {
<li>{{ i }}: {{ item.name }}@if (last) { (last item) }</li>
}
$index is zero-based; $count is the collection’s item count. The first/last and even/odd values describe the current item’s position in the rendered sequence. The Angular control-flow guide documents these contextual values and aliases.
Rank #4
A track expression can use $index, the loop item, and component-class properties or methods. If you alias $index in the let segment, that alias is also available to the tracking expression.
Know the version boundary and migrate from *ngFor
Angular documents built-in control-flow syntax as available from v17. Because @for is built into template syntax, it does not require importing CommonModule for this functionality. The control-flow migration reference provides the migration schematic:
ng generate @angular/core:control-flow
Run it from the Angular workspace to convert eligible control-flow syntax in templates. Review the resulting changes, especially tracking expressions: a key should represent item identity if the collection can change, not merely its current position.
The current NgFor API marks the directive deprecated since Angular v20.0 and recommends @for; removal is intended in a future major release. Applications on Angular v16 or older should follow the version-appropriate Angular control-flow tutorial guidance, which directs those versions to the NgFor documentation. Check the target project’s Angular version and migration guidance before changing templates.
Quick Recap
Limitations to account for
@fordoes not support JavaScriptbreakorcontinue. Filter or prepare the collection before rendering if certain items should be excluded.- Every
@forrequirestrack; there is no untracked form of the block. - Use stable identity for a changing collection. An index-based key is suited to a static collection, not one whose order or membership shifts.
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.
Recommended Free Tools




