Skip to content
This repository was archived by the owner on Jan 5, 2024. It is now read-only.

Commit b4cb7dc

Browse files
committed
fix(ngRepeat): should correctly track elements even when the collection is initially undefined
Closes angular#4145 Closes angular#3964
1 parent 04c9cae commit b4cb7dc

File tree

2 files changed

+26
-6
lines changed

2 files changed

+26
-6
lines changed

src/ng/directive/ngRepeat.js

+6-4
Original file line numberDiff line numberDiff line change
@@ -218,7 +218,8 @@ var ngRepeatDirective = ['$parse', '$animate', function($parse, $animate) {
218218
return function($scope, $element, $attr){
219219
var expression = $attr.ngRepeat;
220220
var match = expression.match(/^\s*(.+)\s+in\s+(.*?)\s*(\s+track\s+by\s+(.+)\s*)?$/),
221-
trackByExp, trackByExpGetter, trackByIdFn, trackByIdArrayFn, trackByIdObjFn, lhs, rhs, valueIdentifier, keyIdentifier,
221+
trackByExp, trackByExpGetter, trackByIdExpFn, trackByIdArrayFn, trackByIdObjFn,
222+
lhs, rhs, valueIdentifier, keyIdentifier,
222223
hashFnLocals = {$id: hashKey};
223224

224225
if (!match) {
@@ -232,7 +233,7 @@ var ngRepeatDirective = ['$parse', '$animate', function($parse, $animate) {
232233

233234
if (trackByExp) {
234235
trackByExpGetter = $parse(trackByExp);
235-
trackByIdFn = function(key, value, index) {
236+
trackByIdExpFn = function(key, value, index) {
236237
// assign key, value, and $index to the locals so that they can be used in hash functions
237238
if (keyIdentifier) hashFnLocals[keyIdentifier] = key;
238239
hashFnLocals[valueIdentifier] = value;
@@ -275,16 +276,17 @@ var ngRepeatDirective = ['$parse', '$animate', function($parse, $animate) {
275276
childScope,
276277
key, value, // key/value of iteration
277278
trackById,
279+
trackByIdFn,
278280
collectionKeys,
279281
block, // last object information {scope, element, id}
280282
nextBlockOrder = [];
281283

282284

283285
if (isArrayLike(collection)) {
284286
collectionKeys = collection;
285-
trackByIdFn = trackByIdFn || trackByIdArrayFn;
287+
trackByIdFn = trackByIdArrayFn || trackByIdExpFn;
286288
} else {
287-
trackByIdFn = trackByIdFn || trackByIdObjFn;
289+
trackByIdFn = trackByIdObjFn || trackByIdExpFn;
288290
// if object, extract keys, sort them and use to determine order of iteration over obj props
289291
collectionKeys = [];
290292
for (key in collection) {

test/ng/directive/ngRepeatSpec.js

+20-2
Original file line numberDiff line numberDiff line change
@@ -841,6 +841,26 @@ describe('ngRepeat', function() {
841841
expect(newLis[1]).toEqual(lis[0]);
842842
expect(newLis[2]).toEqual(lis[1]);
843843
});
844+
845+
it('should be stable even if the collection is initially undefined', function () {
846+
scope.items = undefined;
847+
scope.$digest();
848+
849+
scope.items = [
850+
{ name: 'A' },
851+
{ name: 'B' },
852+
{ name: 'C' }
853+
];
854+
scope.$digest();
855+
856+
lis = element.find('li');
857+
scope.items.shift();
858+
scope.$digest();
859+
860+
var newLis = element.find('li');
861+
expect(newLis.length).toBe(2);
862+
expect(newLis[0]).toBe(lis[1]);
863+
});
844864
});
845865

846866
it('should grow multi-node repeater', inject(function($compile, $rootScope) {
@@ -861,8 +881,6 @@ describe('ngRepeat', function() {
861881
$rootScope.$digest();
862882
expect(element.text()).toEqual('T1:D1;T2:D2;T3:D3;');
863883
}));
864-
865-
866884
});
867885

868886
describe('ngRepeat animations', function() {

0 commit comments

Comments
 (0)