AngularJS ng-repeat, One Time Bindings & Track By

Another interesting lesson yesterday. It was necessary to track by a unique key, so I created a composite key…only to find out I didn’t need to.

A look at ng-repeat

First of all, let’s talk about ng-repeat. The directive is one everybody is familiar with. However, some don’t realize how it works. When a digest cycle occurs, it rerenders its children. It is pretty smart, though. If a developer does not define a track by statement, Angular will generate a $$hashKey property on each object. It checks whether or not the collection order changed, or the references changed by using that $$hashKey. This helps enhance the performance of the repeat, as it will only rerender the items that changed in order or the $$hashKey value changed.

One time bindings inside ng-repeat

There are two things that can be one time bound in an ng-repeat statement. This includes the collection itself (i.e. ng-repeat="item in ::Ctrl.collection) and the elements inside of the repeat.

<div ng-repeat="item in Ctrl.collection">  
<div ng-bind="::item.value"></div>

Enter track by

track by can be utilized to do the same operation as above. It helps performance by not having to generate a $$hashKey for each element in the collection. The track by property must be unique. Developers can use any unique identifier on the objects, or using $index. The $index property is generated on the scope by the ng-repeat and is set to the index of the repeated collection.

What if we swap out the array reference?

This is the scenario I encountered. We have a collection of objects, each having a collection of objects that were being repeated over. When the reference to the outer object changed, it pointed to a new child array on that object.

The solution

One way around this was to generate a unique identifier on each sub collection of each selectable object. This, however, was ugly. I was appending the parent object’s identifier with the index to form 707734582-1 for the sole purpose of tracking. Annoying, but it works.

Front End Developer