The trackBy function (e.g. in an ngFor) provides two arguments: index and item (from the collection being iterated over). Is there a way to pass additional information (as parameters?) to th trackBy function?
My case is that I might be iterating over a variety of types for each instance of my component (which contains the ngFor), with different identifying field names. Ideally, I'd like to be able to pass a third parameter indicating which field in my item should be read.
The trackBy function takes two arguments, the first is the index and the second one is the current item. That will return one unique identifier and the same we can use to track the item. In this example, we are going to track the item id.
The ngFor will use the unique id returned by the trackBy function to track the items. Hence even if we refresh the data from the back end, the unique id will remain the same and the list will not be rendered again. The trackBy takes a function that has two arguments: index and the current item .
The trackBy function takes the index and the current item as arguments and needs to return the unique identifier for this item. Now when you change the collection, Angular can track which items have been added or removed according to the unique identifier and create or destroy only the items that changed. That's all.
If we use the normal *ngFor directive without using the trackBy function, the Angular application will remove all the DOM elements and will recreate them again in the DOM tree, even if the same data is coming.
bind
method can help you to do this trick
template.html
<div *ngFor="let item of items; trackBy: trackByFn.bind(this, 'name')">
{{ item }}
</div>
component.ts
items = [
{
id: 1,
name: 'name1'
},
{
id: 2,
name: 'name2'
}
]
trackByFn(customParam, index, item) {
return item[customParam];
}
I know this question is over a year old now, but I'd like to add another option:
You can create an Angular pipe that takes the additional parameter(s) as arguments and returns a TrackByFunction. The use of such pipe would look as follows:
<div *ngFor="let item of items; trackBy: (myParameter | myTrackByFn)">
The code for the pipe looks as follows:
@Pipe({ name: 'myTrackByFn' })
export class MyTrackByFnPipe implements PipeTransform {
transform<T>(myParameter: any): TrackByFunction<T> {
return (index: number: item: T) => {
// ...
};
}
}
One of the benefits that comes with this approach is that you can reuse the pipe across components, eliminating the need to reimplement a trackBy function in every component.
You can read more about this approach in Ben Nadel's post.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With