Problem:
To render collection in Angular we use the built in directive *ngFor
which works fine as long as we are just displaying or mutating the collection. A potential problem arise when we re-assign the variable holding the collection. Angular must then destroy all the old DOM-nodes and recreate them, even if only a few elements have changed, for a large collection this can create performance issues.
Solution:
Create a function that returns a unique id for each element in the collection, the function is then passed to the directive TrackedBy which we use together with *ngFor
.
Before / Untutored:
Component
items = [
{title: 'Cinnamon buns'},
{title: 'Cup cakes'},
{title: 'Croissants'}
];
update() {
this.items = [
{title: 'Cinnamon buns'},
{title: 'Cup cakes'},
{title: 'Croissants'},
{title: 'Macarons'}
];
}
Template
<div *ngFor="let item of items">
<app-item [text]="item.title"></app-item>
</div>
Log
naive - Cinnamon buns initialized
naive - Cup cakes initialized
naive - Croissants initialized
Updated data
naive - Cinnamon buns initialized
naive - Cup cakes initialized
naive - Croissants initialized
naive - Macarons initialized
After:
Component
items = [
{title: 'Cinnamon buns'},
{title: 'Cup cakes'},
{title: 'Croissants'}
];
update() {
this.items = [
{title: 'Cinnamon buns'},
{title: 'Cup cakes'},
{title: 'Croissants'},
{title: 'Macarons'}
];
}
itemsTrackedBy(index, item) {
return item.text;
}
Template
<div *ngFor="let item of items; trackBy: itemsTrackedBy">
<app-item [text]="item.title"></app-item>
</div>
Log
trackedBy - Cinnamon buns initialized
trackedBy - Cup cakes initialized
trackedBy - Croissants initialized
Updated data
trackedBy - Macarons initialized
Try it yourself:
https://stackblitz.com/edit/thllbrg-angular-fika-2
Official docs:
https://angular.io/guide/template-syntax#ngfor-with-trackby
Top comments (0)