diff options
| author | Misko Hevery | 2013-06-11 13:14:17 -0700 | 
|---|---|---|
| committer | Misko Hevery | 2013-06-11 13:14:34 -0700 | 
| commit | 4953b49761a791d9ea74bcbe78769fec15d91083 (patch) | |
| tree | f8ea43b70ddf4a4428d1c66712793db9ddced8b0 | |
| parent | b28f96949ac477b1fe43c81df7cedc21c7ab184c (diff) | |
| download | angular.js-4953b49761a791d9ea74bcbe78769fec15d91083.tar.bz2 | |
fix(ngRepeat): support growing over multi-element groups
| -rw-r--r-- | src/ng/directive/ngRepeat.js | 35 | ||||
| -rw-r--r-- | test/ng/directive/ngRepeatSpec.js | 20 | 
2 files changed, 38 insertions, 17 deletions
| diff --git a/src/ng/directive/ngRepeat.js b/src/ng/directive/ngRepeat.js index bc46e008..39de8456 100644 --- a/src/ng/directive/ngRepeat.js +++ b/src/ng/directive/ngRepeat.js @@ -245,8 +245,8 @@ var ngRepeatDirective = ['$parse', '$animator', function($parse, $animator) {          //watch props          $scope.$watchCollection(rhs, function ngRepeatAction(collection){            var index, length, -              cursor = $element,     // current position of the node -              nextCursor, +              previousNode = $element[0],     // current position of the node +              nextNode,                // Same as lastBlockMap but it has the current state. It will become the                // lastBlockMap on the next iteration.                nextBlockMap = {}, @@ -288,7 +288,7 @@ var ngRepeatDirective = ['$parse', '$animator', function($parse, $animator) {             } else if (nextBlockMap.hasOwnProperty(trackById)) {               // restore lastBlockMap               forEach(nextBlockOrder, function(block) { -               if (block && block.element) lastBlockMap[block.id] = block; +               if (block && block.startNode) lastBlockMap[block.id] = block;               });               // This is a duplicate and we need to throw an error               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) {            for (key in lastBlockMap) {              if (lastBlockMap.hasOwnProperty(key)) {                block = lastBlockMap[key]; -              animate.leave(block.element); -              forEach(block.element, function(element) { element[NG_REMOVED] = true}); +              animate.leave(block.elements); +              forEach(block.elements, function(element) { element[NG_REMOVED] = true});                block.scope.$destroy();              }            } @@ -316,24 +316,23 @@ var ngRepeatDirective = ['$parse', '$animator', function($parse, $animator) {              value = collection[key];              block = nextBlockOrder[index]; -            if (block.element) { +            if (block.startNode) {                // if we have already seen this object, then we need to reuse the                // associated scope/element                childScope = block.scope; -              nextCursor = cursor[0]; +              nextNode = previousNode;                do { -                nextCursor = nextCursor.nextSibling; -              } while(nextCursor && nextCursor[NG_REMOVED]); +                nextNode = nextNode.nextSibling; +              } while(nextNode && nextNode[NG_REMOVED]); -              if (block.element[0] == nextCursor) { +              if (block.startNode == nextNode) {                  // do nothing -                cursor = block.element;                } else {                  // existing item which got moved -                animate.move(block.element, null, cursor); -                cursor = block.element; +                animate.move(block.elements, null, jqLite(previousNode));                } +              previousNode = block.endNode;              } else {                // new item which we don't know about                childScope = $scope.$new(); @@ -346,12 +345,14 @@ var ngRepeatDirective = ['$parse', '$animator', function($parse, $animator) {              childScope.$last = (index === (arrayLength - 1));              childScope.$middle = !(childScope.$first || childScope.$last); -            if (!block.element) { +            if (!block.startNode) {                linker(childScope, function(clone) { -                animate.enter(clone, null, cursor); -                cursor = clone; +                animate.enter(clone, null, jqLite(previousNode)); +                previousNode = clone;                  block.scope = childScope; -                block.element = clone; +                block.startNode = clone[0]; +                block.elements = clone; +                block.endNode = clone[clone.length - 1];                  nextBlockMap[block.id] = block;                });              } diff --git a/test/ng/directive/ngRepeatSpec.js b/test/ng/directive/ngRepeatSpec.js index ac6ceb83..2a0d5284 100644 --- a/test/ng/directive/ngRepeatSpec.js +++ b/test/ng/directive/ngRepeatSpec.js @@ -753,4 +753,24 @@ describe('ngRepeat ngAnimate', function() {        }    })); +  it('should grow multi-node repeater', inject(function($compile, $rootScope) { +    $rootScope.show = false; +    $rootScope.books = [ +      {title:'T1', description: 'D1'}, +      {title:'T2', description: 'D2'} +    ]; +    element = $compile( +        '<div>' + +            '<dt ng-repeat-start="book in books">{{book.title}}:</dt>' + +            '<dd ng-repeat-end>{{book.description}};</dd>' + +        '</div>')($rootScope); + +    $rootScope.$digest(); +    expect(element.text()).toEqual('T1:D1;T2:D2;'); +    $rootScope.books.push({title:'T3', description: 'D3'}); +    $rootScope.$digest(); +    expect(element.text()).toEqual('T1:D1;T2:D2;T3:D3;'); +  })); + +  }); | 
