diff options
| author | Tobias Bosch | 2013-11-26 19:55:02 -0800 |
|---|---|---|
| committer | Tobias Bosch | 2013-12-05 22:16:25 -0800 |
| commit | b0972a2e75909e41dbac6e4413ada7df2d51df3a (patch) | |
| tree | daefd834b62abcbe3ff970e2942cca16f67c491d /src/ng/directive/ngRepeat.js | |
| parent | 2dbb6f9a54eb5ff5847eed11c85ac4cf119eb41c (diff) | |
| download | angular.js-b0972a2e75909e41dbac6e4413ada7df2d51df3a.tar.bz2 | |
fix($compile): update cloned elements if the template arrives after the cloning
If an element has a directive whose content is loaded using `templateUrl`,
and the element is cloned using a linking function before the template arrives,
the clone needs to be updated as well.
This also updates `ngIf` and `ngRepeat` to keep the connection to the clone
of a tranclude function, so that they know about the changes a directive with
`templateUrl` does to the element in the future.
Fixes to #4930.
Diffstat (limited to 'src/ng/directive/ngRepeat.js')
| -rw-r--r-- | src/ng/directive/ngRepeat.js | 30 |
1 files changed, 20 insertions, 10 deletions
diff --git a/src/ng/directive/ngRepeat.js b/src/ng/directive/ngRepeat.js index cd605bf3..86874a41 100644 --- a/src/ng/directive/ngRepeat.js +++ b/src/ng/directive/ngRepeat.js @@ -301,7 +301,7 @@ var ngRepeatDirective = ['$parse', '$animate', function($parse, $animate) { } else if (nextBlockMap.hasOwnProperty(trackById)) { // restore lastBlockMap forEach(nextBlockOrder, function(block) { - if (block && block.startNode) lastBlockMap[block.id] = block; + if (block && block.scope) lastBlockMap[block.id] = block; }); // This is a duplicate and we need to throw an error throw ngRepeatMinErr('dupes', "Duplicates in a repeater are not allowed. Use 'track by' expression to specify unique keys. Repeater: {0}, Duplicate key: {1}", @@ -318,7 +318,7 @@ var ngRepeatDirective = ['$parse', '$animate', function($parse, $animate) { // lastBlockMap is our own object so we don't need to use special hasOwnPropertyFn if (lastBlockMap.hasOwnProperty(key)) { block = lastBlockMap[key]; - elementsToRemove = getBlockElements(block); + elementsToRemove = getBlockElements(block.clone); $animate.leave(elementsToRemove); forEach(elementsToRemove, function(element) { element[NG_REMOVED] = true; }); block.scope.$destroy(); @@ -330,9 +330,9 @@ var ngRepeatDirective = ['$parse', '$animate', function($parse, $animate) { key = (collection === collectionKeys) ? index : collectionKeys[index]; value = collection[key]; block = nextBlockOrder[index]; - if (nextBlockOrder[index - 1]) previousNode = nextBlockOrder[index - 1].endNode; + if (nextBlockOrder[index - 1]) previousNode = getBlockEnd(nextBlockOrder[index - 1]); - if (block.startNode) { + if (block.scope) { // if we have already seen this object, then we need to reuse the // associated scope/element childScope = block.scope; @@ -342,11 +342,11 @@ var ngRepeatDirective = ['$parse', '$animate', function($parse, $animate) { nextNode = nextNode.nextSibling; } while(nextNode && nextNode[NG_REMOVED]); - if (block.startNode != nextNode) { + if (getBlockStart(block) != nextNode) { // existing item which got moved - $animate.move(getBlockElements(block), null, jqLite(previousNode)); + $animate.move(getBlockElements(block.clone), null, jqLite(previousNode)); } - previousNode = block.endNode; + previousNode = getBlockEnd(block); } else { // new item which we don't know about childScope = $scope.$new(); @@ -362,14 +362,16 @@ var ngRepeatDirective = ['$parse', '$animate', function($parse, $animate) { childScope.$odd = !(childScope.$even = (index&1) === 0); // jshint bitwise: true - if (!block.startNode) { + if (!block.scope) { $transclude(childScope, function(clone) { clone[clone.length++] = document.createComment(' end ngRepeat: ' + expression + ' '); $animate.enter(clone, null, jqLite(previousNode)); previousNode = clone; block.scope = childScope; - block.startNode = previousNode && previousNode.endNode ? previousNode.endNode : clone[0]; - block.endNode = clone[clone.length - 1]; + // Note: We only need the first/last node of the cloned nodes. + // However, we need to keep the reference to the jqlite wrapper as it might be changed later + // by a directive with templateUrl when it's template arrives. + block.clone = clone; nextBlockMap[block.id] = block; }); } @@ -378,5 +380,13 @@ var ngRepeatDirective = ['$parse', '$animate', function($parse, $animate) { }); } }; + + function getBlockStart(block) { + return block.clone[0]; + } + + function getBlockEnd(block) { + return block.clone[block.clone.length - 1]; + } }]; |
