Say that I'm ng-repeat
ing 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.
Thoughts?
Also, what if src
+ caption
was ensured to be unique? How can I track by
multiple properties?
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)
?
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.