Angular ‘track by’ With Strings
One of the interesting things about ng-repeat is that it doesn’t like repeats. I first encountered this interesting quirk when I was writing a program to practice typing. We often re-use words in spoken languages, so when I used `ng-repeat=‘word in document.wordArray’` I was greeted with the error:
Error: [ngRepeat:dupes] Duplicates in a repeater are not allowed. Use ‘track by’ expression to specify unique keys. Repeater: target in input.docArr | scrollFilter:input.count, Duplicate key: string:the, Duplicate value: the
After some research it became clear why this was happening. ng-repeat uses keys (with default key value of the object’s $id) to track DOM nodes with items. This becomes a problem when we use strings. For example:
<div ng-repeat=‘word in [“the”, “cat”, “ate”, “the”, “mouse”]’></div>
Here we’re using “the” twice, and angular can’t evaluate an $id property of a string, so it will not know which word is to track when an event happens to the word “the” — it has to be ready for anything!
Enter `track by`
The solution given by the documentation, and several other sources, is to use `track by $index`. This is great because it tells ng-repeat, “hey, don’t look at these as unique words, but look at them as indexed objects”. In other words, don’t track the array, [“the”, “cat”, “ate”, “the”, “mouse”], but track [0,1,2,3,4], while using the same words.
Problem solved! Now when “the” at index zero is changed, ng-repeat will never think it’s “the” at index 3.
For fantastic insights into the performance benefits of ‘track by’ with primitive objects, check-out Ben Nadel’s blog post.