Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how to use track by inside ngFor angular 2

tried every syntax i can guess couldnt make it works !

<!--- THIS WORKS FINE ---> <ion-card *ngFor="#post of posts"> {{post|json}} </ion-card>  <!--- BLANK PAGE ---> <ion-card *ngFor="#post of posts track by post.id"> {{post|json}} </ion-card>  <!--- Exception : Cannot read property 'id' of undefined ---> <ion-card *ngFor="#post of posts;trackBy:post.id"> {{post|json}} </ion-card>  <!--- Exception : Cannot read property 'undefined' of undefined ---> <ion-card *ngFor="#post of posts;trackBy:posts[index].id"> {{post|json}} </ion-card>  <!--- Blank page no exception raised !  ---> <ion-card *ngFor="#post of posts;#index index;trackBy:posts[index].id"> {{post|json}} </ion-card> 

the only approach that worked for me was

  1. Creating method in controller Class

    identify(index,post:Post){ return post.id }

and

<ion-card *ngFor="#post of posts;trackBy:identify"> </ion-card> 

is this is only way ? can i not just specify a property name inline for trackBy ?

like image 251
Zalaboza Avatar asked Mar 31 '16 01:03

Zalaboza


People also ask

What is trackBy in ngFor Angular?

TrackBy is used to track the latest value in the dom without refreshing the full dom element. It only updates the new data. Prerequisites. Basic knowledge of Angular. Visual Studio Code must be installed.

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.

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.

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

Why use trackyBy with ngFor directive : ngFor directive may perform poorly with large lists. A small change to the list like, adding a new item or removing an existing item may trigger several DOM manipulations.


2 Answers

As pointed out in @Eric comment, and after lots of reading and playing around, here is how to use trackBy in angular2

  1. the first thing you need to know its not same syntax as angular1, now you need to separate it from the for loop with a ;.

Usage 1: Track by property of object

 // starting v2. 1 this will throw error, you can only use functions in trackBy from now on  <ion-card *ngFor="let post of posts;trackBy:post?.id"> </ion-card> // **DEPRECATED** ---or--- <ion-card *ngFor="let post of posts;trackBy:trackByFn"> </ion-card> 

here you ask angular2 to

  1. create a local variable post;
  2. you tell trackBy to wait untill this local variable is ready "you do that by using elvis operator 'the question mark after the variable name', then use its id as tracker.

so

// starting v2. 1 this will throw error, you can only use functions in trackBy from now on  *ngFor="#post of posts;trackBy:post?.id" 

is what same as angular's 1

ng-repeat="post in posts track by post.id" 

Usage 2: Track using your own Function

@Page({     template: `         <ul>             <li *ngFor="#post of posts;trackBy:identify">               {{post.data}}             </li>         </ul>     ` }) export class HomeworkAddStudentsPage {     posts:Array<{id:number,data:string}>;         constructor() {         this.posts = [  {id:1,data:'post with id 1'},                         {id:2,data:'post with id 2'} ];     }      identify(index,item){       //do what ever logic you need to come up with the unique identifier of your item in loop, I will just return the object id.       return post.id       }  } 

trackBy can take a name of callback, and it will call it for us supplying 2 parameters: the index of the loop and the current item.

To achieve the same with Angular 1, I used to do:

<li ng-repeat="post in posts track by identify($index,post)"></li>  app.controller(function($scope){   $scope.identify = function(index, item) {return item.id}; }); 
like image 196
Zalaboza Avatar answered Oct 03 '22 20:10

Zalaboza


As you already recognized, using a function is the only way to use trackBy in Angular 2

<ion-card *ngFor="#post of posts;trackBy:identify"></ion-card> 

The official documentation states that https://angular.io/docs/ts/latest/api/common/index/NgFor-directive.html

All the other information about <ion-card *ngFor="let post of posts;trackBy:post?.id"></ion-card> is wrong. Starting with Angular 2.4.1 this will also throw an error in the application.

like image 45
Volker Andres Avatar answered Oct 03 '22 22:10

Volker Andres