Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When not to use 'track by $index' in an AngularJS ng-repeat?

I recently got the console error `

Error: [ngRepeat:dupes] duplicates in a repeater are not allowed. Use 'track by' expression to specify unique keys...

— AngularJS Error Reference - ngRepeat:dupes

which I then used 'track by $index' and the issue was solved...

But that got me thinking... is there a reason why you wouldn't want to use track by $index in an ng-repeat?

I've read SO questions like this one as well as other articles, but it seems like almost all of the articles only talk about the advantages of using 'track by'.

Can someone list the disadvantages and give an example of when you wouldn't want to use track by $index?

like image 311
Kyle Krzeski Avatar asked Aug 16 '17 18:08

Kyle Krzeski


People also ask

What is ngrepeat track by $Index in angular?

The ngRepeat track by $index allows you to specify which items should be repeated using their index number. The ngRepeat is a directive that can be added to the HTML template of an Angular application. It is used for creating lists, and it can take an expression as an argument.

How to track elements in an array in angular?

Note: The index starts from 0 not 1. Angular also provides the reserved first and last keywords for getting the first and last items in the array. Angular provides the trackBy feature which allows you to track elements when they are added or removed from the array for performance reasons.

How to iterate over an array using ngfor in angular?

We can use the ngFor directive to iterate over arrays of data right in the Angular’s component template. We can use other features like index, first, last and trackBy to get the index of the current element, the first and last elements and for tracking the addition or removal of the array elements for performane reasons.

What is $Index in Angular 2?

Technically $index is a “template variable” created by ng-repeat. It’s only accurate and has meaning inside the repeat block. When we pass the value out, it loses its context and it’s no longer valid.


2 Answers

There are multiple reasons to avoid track by $index

  • Avoid using track by $index when using one-time bindings
  • Avoid track by $index when there is a unique property identifier
  • Other Examples of problems with track by $index

Avoid using track by $index when using one-time bindings

The documentation specifically states that track by $index should be avoided when using one-time bindings.

From the Docs:

Avoid using track by $index when the repeated template contains one-time bindings. In such cases, the nth DOM element will always be matched with the nth item of the array, so the bindings on that element will not be updated even when the corresponding item changes, essentially causing the view to get out-of-sync with the underlying data.

— AngularJS ng-repeat Reference - Tracking and Duplicates


Avoid track by $index when there is a unique property identifier

Avoid track by $index when there is a unique property identifier to work with. When working with objects that are all unique, it is better to let ng-repeat to use its own tracking instead of overriding with track by $index.

From the Docs:

If you are working with objects that have a unique identifier property, you should track by this identifier instead of the object instance. Should you reload your data later, ngRepeat will not have to rebuild the DOM elements for items it has already rendered, even if the JavaScript objects in the collection have been substituted for new ones. For large collections, this significantly improves rendering performance.

— AngularJS ng-repeat Directive API Reference - Tracking


Other Examples of problems with track by $index

I have also seen problems when objects are added and removed from arrays of objects.

  • Problems with track by $index with Angular UI Carousel
  • Ng-Repeat showing irregular behavior with one time binding
  • Angular: Updating $scope with new data causes old data to remain when using ng-repeat
  • Trouble with AngularJS and Select binding not loading default value
like image 90
georgeawg Avatar answered Oct 29 '22 11:10

georgeawg


It has a disadvantage,

'track by' expression tracks by index in the array. It means that as long as the index stays the same, angularjs thinks it's the same object.

So if you replace any object in the array, angularjs think it didn't change because the index in the array is still the same. Because of that the change detection wont trigger when you expect it would.

Take a look at this example

Try to change the name, nothing happens. Remove track by index, it works. add track by item.name, it still works.

like image 38
Sajeetharan Avatar answered Oct 29 '22 09:10

Sajeetharan