I can't really understand what I should return from trackBy. Based on some examples I've seen on the web, I should return the value of some property on the object. Is it right? Why should I get index as a parameter?
For example, in the following case:
Component.component.ts
constructor() {
window.setInterval(() => this.users = [
{ name: 'user1', score: Math.random() },
{ name: 'user2', score: Math.random() }
],
1000);
}
userByName(index, user) {
return user.name;
}
Component.template.html
<div *ngFor="let user of users; trackBy:userByName">
{{user.name}} -> {{user.score}}
</div>
The objects shown in this template are still updated despite the name being unchanged. Why?
On each
ngDoChecktriggered for thengForOfdirective, Angular checks what objects have changed. It uses differs for this process and each differ uses thetrackByfunction to compare the current object with the new one. The defaulttrackByfunction tracks items by identity:It receives the current item and should return some value. Then the value returned by the function is compared against the value this function returned the last time. If the value changes, the differ reports a change. So if the default function returns object references, it will not match the current item if the object reference has changed. So you can provide your custom
trackByfunction that will return something else. For example, some key value of the object. If this key value matches the previous one, then Angular will not detect the change.The syntax
...trackBy:userByNameis no longer supported. You must now provide a function reference. Here is the basic example:Although the object reference changes, the DOM is not updated. Here is the plunker. If you're curious how
ngForworks under the hood, read this answer.