I can't really understand what I should return from trackBy
. Based on examples I've seen on the web, I should return the value of some property on the object. Is it correct? Why do I get index as a parameter?
For example, in the following case:
constructor() {
window.setInterval(() => this.users = [
{name: 'user1', score: Math.random()},
{name: 'user2', score: Math.random()}],
1000);
}
userByName(index, user) {
return user.name;
}
...
<div *ngFor="let user of users; trackBy:userByName">{{user.name}} -> {{user.score}}</div>
The objects shown in template are still updated despite the name being unchanged. Why?
else you can use
and
and
On each
ngDoCheck
triggered for thengForOf
directive Angular checks what objects have changed. It uses differs for this process and each differ usestrackBy
function to compare the current object with the new one. The defaulttrackBy
function 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
trackBy
function 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:userByName
is 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
ngFor
works under the hood, read this answer.This angular
NgFor
document will help you. https://angular.io/docs/ts/latest/api/common/index/NgFor-directive.htmlBelow example for your code
As this topic is still active & find a clear answer is difficult let me add few examples in addition to @Max's answer:
app.component.ts
Let's display the
array
into 3 div using*ngFor
.app.component.html
Example of
*ngFor
without trackBy:What happend if we click on
foo
button ?→ The 3 divs will be refreshed. Try it yourself, open your console to verify.
Example of
*ngFor
with trackBy:What happend if we click on
foo
button ?→ Only the first div will be refreshed. Try it yourself, open your console to verify.
And what if we updated the first object instead of the whole object ?
→ There is no need to use
trackBy
here.It's especially usefull when using Subscription which often looks like what I schematized with
array
. So it would looks like:From documentation:
Read more here: https://angular.io/api/common/NgForOf
Find my original answer here: https://stackoverflow.com/a/57890227/9753985