Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ngFor trackBy function with custom parameters

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.

like image 895
skeej Avatar asked Oct 03 '17 19:10

skeej


People also ask

How do you use the trackBy function?

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.

What is the difference between trackBy and ngFor?

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 .

How does ngFor trackBy work?

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.

Why must you use the ngFor directive in conjunction with the trackBy function?

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.


Video Answer


2 Answers

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];
}
like image 67
yurzui Avatar answered Sep 18 '22 13:09

yurzui


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.

like image 24
Sam Herrmann Avatar answered Sep 17 '22 13:09

Sam Herrmann