Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Understanding the ngRepeat 'track by' expression

I'm having difficulties understanding how the track by expression of ng-repeat in angularjs works. The documentation is very scarce: http://docs.angularjs.org/api/ng/directive/ngRepeat

Can you explain what the difference between those two snippets of code is in terms of databinding and other relevant aspects?

with: track by $index

<!--names is an array-->
<div ng-repeat="(key, value) in names track by $index">
  <input ng-model="value[key]">                         
</div>

without (same output)

<!--names is an array-->
<div ng-repeat="(key, value) in names">
   <input ng-model="value[key]">                         
</div>
like image 259
Jonathan Grupp Avatar asked Mar 31 '14 12:03

Jonathan Grupp


People also ask

How do I use track in NG-repeat?

To avoid this problem, you can use "track by" with ng-repeat. In track by you have to use angular expression that will be used to uniquely identify the each items in collection or model. "track by" tells the angular js that how angular js will track the association between DOM and the model (i.e. collection).

How do you use track by?

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 Ngrepeat?

AngularJS ng-repeat Directive The ng-repeat directive repeats a set of HTML, a given number of times. The set of HTML will be repeated once per item in a collection. The collection must be an array or an object. Note: Each instance of the repetition is given its own scope, which consist of the current item.

What is use track by in angular?

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.


3 Answers

You can track by $index if your data source has duplicate identifiers

e.g.: $scope.dataSource: [{id:1,name:'one'}, {id:1,name:'one too'}, {id:2,name:'two'}]

You can't iterate this collection while using 'id' as identifier (duplicate id:1).

WON'T WORK:

<element ng-repeat="item.id as item.name for item in dataSource">
  // something with item ...
</element>

but you can, if using track by $index:

<element ng-repeat="item in dataSource track by $index">
  // something with item ...
</element>
like image 111
nilsK Avatar answered Oct 20 '22 00:10

nilsK


a short summary:

track by is used in order to link your data with the DOM generation (and mainly re-generation) made by ng-repeat.

when you add track by you basically tell angular to generate a single DOM element per data object in the given collection

this could be useful when paging and filtering, or any case where objects are added or removed from ng-repeat list.

usually, without track by angular will link the DOM objects with the collection by injecting an expando property - $$hashKey - into your JavaScript objects, and will regenerate it (and re-associate a DOM object) with every change.

full explanation:

http://www.bennadel.com/blog/2556-using-track-by-with-ngrepeat-in-angularjs-1-2.htm

a more practical guide:

http://www.codelord.net/2014/04/15/improving-ng-repeat-performance-with-track-by/

(track by is available in angular > 1.2 )

like image 33
Nuriel Avatar answered Oct 20 '22 00:10

Nuriel


If you are working with objects track by the identifier(e.g. $index) instead of the whole object and you reload your data later, ngRepeat will not rebuild the DOM elements for items it has already rendered, even if the JavaScript objects in the collection have been substituted for new ones.

like image 9
ram1993 Avatar answered Oct 20 '22 00:10

ram1993