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

Commit 4953b49

Browse files
committed
fix(ngRepeat): support growing over multi-element groups
1 parent b28f969 commit 4953b49

File tree

2 files changed

+38
-17
lines changed

2 files changed

+38
-17
lines changed

src/ng/directive/ngRepeat.js

+18-17
Original file line numberDiff line numberDiff line change
@@ -245,8 +245,8 @@ var ngRepeatDirective = ['$parse', '$animator', function($parse, $animator) {
245245
//watch props
246246
$scope.$watchCollection(rhs, function ngRepeatAction(collection){
247247
var index, length,
248-
cursor = $element, // current position of the node
249-
nextCursor,
248+
previousNode = $element[0], // current position of the node
249+
nextNode,
250250
// Same as lastBlockMap but it has the current state. It will become the
251251
// lastBlockMap on the next iteration.
252252
nextBlockMap = {},
@@ -288,7 +288,7 @@ var ngRepeatDirective = ['$parse', '$animator', function($parse, $animator) {
288288
} else if (nextBlockMap.hasOwnProperty(trackById)) {
289289
// restore lastBlockMap
290290
forEach(nextBlockOrder, function(block) {
291-
if (block && block.element) lastBlockMap[block.id] = block;
291+
if (block && block.startNode) lastBlockMap[block.id] = block;
292292
});
293293
// This is a duplicate and we need to throw an error
294294
throw ngError(50, "ngRepeat error! Duplicates in a repeater are not allowed. Use 'track by' expression to specify unique keys. Repeater: {0}, Duplicate key: {1}",
@@ -304,8 +304,8 @@ var ngRepeatDirective = ['$parse', '$animator', function($parse, $animator) {
304304
for (key in lastBlockMap) {
305305
if (lastBlockMap.hasOwnProperty(key)) {
306306
block = lastBlockMap[key];
307-
animate.leave(block.element);
308-
forEach(block.element, function(element) { element[NG_REMOVED] = true});
307+
animate.leave(block.elements);
308+
forEach(block.elements, function(element) { element[NG_REMOVED] = true});
309309
block.scope.$destroy();
310310
}
311311
}
@@ -316,24 +316,23 @@ var ngRepeatDirective = ['$parse', '$animator', function($parse, $animator) {
316316
value = collection[key];
317317
block = nextBlockOrder[index];
318318

319-
if (block.element) {
319+
if (block.startNode) {
320320
// if we have already seen this object, then we need to reuse the
321321
// associated scope/element
322322
childScope = block.scope;
323323

324-
nextCursor = cursor[0];
324+
nextNode = previousNode;
325325
do {
326-
nextCursor = nextCursor.nextSibling;
327-
} while(nextCursor && nextCursor[NG_REMOVED]);
326+
nextNode = nextNode.nextSibling;
327+
} while(nextNode && nextNode[NG_REMOVED]);
328328

329-
if (block.element[0] == nextCursor) {
329+
if (block.startNode == nextNode) {
330330
// do nothing
331-
cursor = block.element;
332331
} else {
333332
// existing item which got moved
334-
animate.move(block.element, null, cursor);
335-
cursor = block.element;
333+
animate.move(block.elements, null, jqLite(previousNode));
336334
}
335+
previousNode = block.endNode;
337336
} else {
338337
// new item which we don't know about
339338
childScope = $scope.$new();
@@ -346,12 +345,14 @@ var ngRepeatDirective = ['$parse', '$animator', function($parse, $animator) {
346345
childScope.$last = (index === (arrayLength - 1));
347346
childScope.$middle = !(childScope.$first || childScope.$last);
348347

349-
if (!block.element) {
348+
if (!block.startNode) {
350349
linker(childScope, function(clone) {
351-
animate.enter(clone, null, cursor);
352-
cursor = clone;
350+
animate.enter(clone, null, jqLite(previousNode));
351+
previousNode = clone;
353352
block.scope = childScope;
354-
block.element = clone;
353+
block.startNode = clone[0];
354+
block.elements = clone;
355+
block.endNode = clone[clone.length - 1];
355356
nextBlockMap[block.id] = block;
356357
});
357358
}

test/ng/directive/ngRepeatSpec.js

+20
Original file line numberDiff line numberDiff line change
@@ -753,4 +753,24 @@ describe('ngRepeat ngAnimate', function() {
753753
}
754754
}));
755755

756+
it('should grow multi-node repeater', inject(function($compile, $rootScope) {
757+
$rootScope.show = false;
758+
$rootScope.books = [
759+
{title:'T1', description: 'D1'},
760+
{title:'T2', description: 'D2'}
761+
];
762+
element = $compile(
763+
'<div>' +
764+
'<dt ng-repeat-start="book in books">{{book.title}}:</dt>' +
765+
'<dd ng-repeat-end>{{book.description}};</dd>' +
766+
'</div>')($rootScope);
767+
768+
$rootScope.$digest();
769+
expect(element.text()).toEqual('T1:D1;T2:D2;');
770+
$rootScope.books.push({title:'T3', description: 'D3'});
771+
$rootScope.$digest();
772+
expect(element.text()).toEqual('T1:D1;T2:D2;T3:D3;');
773+
}));
774+
775+
756776
});

0 commit comments

Comments
 (0)