2

Say that I'm ng-repeating over images, which is an array of objects that have a src and a caption property.

var images = [
  {src: 'a.jpg', caption: 'a'},
  {src: 'b.jpg', caption: 'b'},
  {src: 'c.jpg', caption: 'c'},
  {src: 'd.jpg', caption: 'd'},
  {src: 'e.jpg', caption: 'e'},
  {src: 'f.jpg', caption: 'f'},
  {src: 'g.jpg', caption: 'g'},
  {src: 'h.jpg', caption: 'h'},
  {src: 'i.jpg', caption: 'i'},
  {src: 'j.jpg', caption: 'j'},
];

Assume that there could be duplicate images, so a src + caption combination doesn't ensure uniqueness. I want to track by, but there doesn't appear to be a way to do it other than $index.

$index seems like a bad solution to me. Imagine that the first image (a) was removed. Then the index of all subsequent images would be changed, and thus the whole list would have to be rerendered. This isn't too bad with a list of 10 items, but it is with bigger lists.

  1. Thoughts?

  2. Also, what if src + caption was ensured to be unique? How can I track by multiple properties?

  3. Does track by work by putting the tracked property onto $$watchers? Like is track by image.id doing something like $scope.$watch(image.id, cb)?

Adam Zerner
  • 17,797
  • 15
  • 90
  • 156

1 Answers1

6

1) You have it right. $index is the only way to go given your constraints, and it is not optimal.

2) The syntax is "track by expression". Expression can be any valid angular expression, so

track by image.src + image.caption

is perfectly valid.

3) track by doesn't use watchers. the ngRepeat directive maintains an internal map of models and DOM nodes indexed by the track by expression. It tries to reuse DOM nodes (and scopes) where possible. The only thing it $watches is the collection.

Joe Enzminger
  • 11,110
  • 3
  • 50
  • 75
  • Thanks! Would you mind elaborating a bit more on 3)? I've been trying to research it, but can't find anything going into the depth I'm looking for. – Adam Zerner Mar 09 '15 at 00:38
  • The best resource would be to look at the [source for ngRepeat on github](https://github.com/angular/angular.js/blob/master/src/ng/directive/ngRepeat.js). The expensive part of ngRepeat is the construction of new scopes and DOM nodes. ngRepeat tries to avoid this by using the already created nodes when the underlying collection changes. – Joe Enzminger Mar 09 '15 at 00:40