Last Updated: February 25, 2016
·
2.874K
· lucasroesler

Angular track by optimization and arrays

If you do a search on the web for Angular ng-repeat, you will of course get the documentation for ng-repeat, but you will also find several blog posts about how to optimize ng-repeat by using the track by option. See http://www.codelord.net/2014/04/15/improving-ng-repeat-performance-with-track-by/, for example. Aviv uses the following example

<ul class="tasks">
    <li ng-repeat="task in tasks" ng-class="{done: task.done}">
        {{task.id}}: {{task.title}}
    </li>
</ul>

Here the code assumes an array of task objects, e.g.

$scope.tasks = [{id: 1, title: "First task"}, ...]

With this code, when tasks is updated, say a new task is pushed on the end of the array, Angular will deconstruct and completely build the li elements in the ng-repeat. It would be awesome if angular only updated the modified tasks and the related DOM elements. We can do this with the simple change of

ng-repeat="task in tasks track by $index"

of

ng-repeat="task in tasks track by task.id"

However, track by can seems like a bug if you are repeating a list like the following [0,0,1,2,3] and it updated to [0,1,2,3,4]. In this case, the tracking value, $index, never changes, so the DOM elements will not be updated. Here is my fix:

ng-repeat="value in arrasy track by array_hash($index, value)"

where

$scope.array_hash = function(index, value) {
    return String($index) + '-' + String(value);
}

Now, the track by value changes for both index and value changes. Of course there are problems here, I am assuming that String(value) makes sense. You will have to modify as appropriate for your use case.

Have a fresh tip? Share with Coderwall community!

Post
Post a tip
Did you know?

JavaScript on a page runs with the privileges of that origin. One altered library, tag manager, or snippet can read inputs, change what people see, and call your APIs as the user.

Security insights from Cside