Use `trackBy` with `ngFor` when an update replaces objects that still represent the same data. Without it, `ngFor` may destroy and recreate HTML elements even when little has changed. A tracking method lets Angular recognize equivalent objects and move existing elements instead. section 12.2.3
Track product rows by name
Define `getKey(index: number, product: Product) { return product.name; }` on the component, then add `trackBy:getKey` to the row’s `*ngFor` expression. The method receives the item’s position and the item; matching results identify equivalent items. In this example, replacing a Product with a different object of the same name lets Angular retain and move its row rather than recreate it. Other directives can still change content within that row. section 12.2.3
Listing 12.13. Providing an equality method in the template.html file in the src/app folder
<div class="text-white">
<div class="bg-info p-2">
There are {{count()}} products.
</div>
<div class="p-1">
<table class="table table-sm table-bordered text-dark">
<tr><th></th><th>Name</th><th>Category</th><th>Price</th></tr>
<tr *ngFor="let item of products(); let i = index;
let c = count; let odd = odd; let first = first;
let last = last; trackBy:getKey"
class="text-white" [class.bg-primary]="odd"
[class.bg-info]="!odd"
[class.bg-warning]="first || last">
<td>{{ i + 1 }} of {{ c }}</td>
<td>{{item.name}}</td>
<td>{{item.category}}</td>
<td *ngIf="!last">{{item.price}}</td>
</tr>
</table>
</div>
</div>
<button class="btn btn-info text-white mt-2" (click)="removeProduct()">
Remove
</button>
<button class="btn btn-info text-white mt-2 mx-2" (click)="swapProduct()">
Swap
</button>
The template listing shows where `trackBy:getKey` fits alongside other `ngFor` values. section 12.2.3
