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
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 ?
This simple solution worked for my scenario
EDIT: As suggested by Jeremy Thille below, you should use
let
instead of#
, as#
is deprecated in the latest versions of Angular2.As pointed out in @Eric comment, and after lots of reading and playing around, here is how to use trackBy in angular2
;
.Usage 1: Track by property of object
here you ask angular2 to
so
is what same as angular's 1
Usage 2: Track using your own Function
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:
Just want to add few examples (Angular 2+) in addition to others' answer to make the use of trackBy clear.
From documentation:
Read more here: https://angular.io/api/common/NgForOf
An example will explain it better.
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:As you already recognized, using a function is the only way to use
trackBy
in Angular 2The 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.The concept behind trackBy:
ngFor
of angular automatically optimizes the display of modified/created/deleted objects by tracking through object identity. So, if you create all new objects in the list and then usengFor
, it will render whole list.Let's consider a scenario where despite of all
ngFor
optimizations, the rendering is still taking time. In that case we usetrackBy
. So that, we can provide another parameter to track objects than the object identity which is a default tracking criteria.A running example: