-
Notifications
You must be signed in to change notification settings - Fork 27.4k
Nested transclusion issues #7565
Changes from all commits
a5ca9f7
d48d129
bcab5ac
83194e6
120c592
79674f9
dfc3e81
cd11938
cd98b7a
de29c24
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -264,7 +264,6 @@ var ngRepeatDirective = ['$parse', '$animate', function($parse, $animate) { | |
// lastBlockMap on the next iteration. | ||
nextBlockMap = {}, | ||
arrayLength, | ||
childScope, | ||
key, value, // key/value of iteration | ||
trackById, | ||
trackByIdFn, | ||
|
@@ -273,6 +272,17 @@ var ngRepeatDirective = ['$parse', '$animate', function($parse, $animate) { | |
nextBlockOrder = [], | ||
elementsToRemove; | ||
|
||
var updateScope = function(scope, index) { | ||
scope[valueIdentifier] = value; | ||
if (keyIdentifier) scope[keyIdentifier] = key; | ||
scope.$index = index; | ||
scope.$first = (index === 0); | ||
scope.$last = (index === (arrayLength - 1)); | ||
scope.$middle = !(scope.$first || scope.$last); | ||
// jshint bitwise: false | ||
scope.$odd = !(scope.$even = (index&1) === 0); | ||
// jshint bitwise: true | ||
}; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @vojtajina - This function was originally just a block of code. It could still be as it is only called once. Should we revert that, since I guess that creating a function in here is a performance cost? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yep, inlining might be better. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There is more important issue however - this is the reason why the google internal tests are failing (it's a regression in Angular). The ng-repeat state is set AFTER the transclusion is linked. That is wrong. It's pretty scary that we don't have any test for this (all the existing tests assert through binding which eventually contains the value even if the state is set later). This branch shows the problem (failing test) including possible fix (the test is passing): https://github.com/vojtajina/angular.js/tree/pr-7565-ng-repeat-state-set-after-transclusion-issue |
||
|
||
if (isArrayLike(collection)) { | ||
collectionKeys = collection; | ||
|
@@ -281,9 +291,9 @@ var ngRepeatDirective = ['$parse', '$animate', function($parse, $animate) { | |
trackByIdFn = trackByIdExpFn || trackByIdObjFn; | ||
// if object, extract keys, sort them and use to determine order of iteration over obj props | ||
collectionKeys = []; | ||
for (key in collection) { | ||
if (collection.hasOwnProperty(key) && key.charAt(0) != '$') { | ||
collectionKeys.push(key); | ||
for (var itemKey in collection) { | ||
if (collection.hasOwnProperty(itemKey) && itemKey.charAt(0) != '$') { | ||
collectionKeys.push(itemKey); | ||
} | ||
} | ||
collectionKeys.sort(); | ||
|
@@ -319,10 +329,10 @@ var ngRepeatDirective = ['$parse', '$animate', function($parse, $animate) { | |
} | ||
|
||
// remove existing items | ||
for (key in lastBlockMap) { | ||
for (var blockKey in lastBlockMap) { | ||
// lastBlockMap is our own object so we don't need to use special hasOwnPropertyFn | ||
if (lastBlockMap.hasOwnProperty(key)) { | ||
block = lastBlockMap[key]; | ||
if (lastBlockMap.hasOwnProperty(blockKey)) { | ||
block = lastBlockMap[blockKey]; | ||
elementsToRemove = getBlockElements(block.clone); | ||
$animate.leave(elementsToRemove); | ||
forEach(elementsToRemove, function(element) { element[NG_REMOVED] = true; }); | ||
|
@@ -340,8 +350,6 @@ var ngRepeatDirective = ['$parse', '$animate', function($parse, $animate) { | |
if (block.scope) { | ||
// if we have already seen this object, then we need to reuse the | ||
// associated scope/element | ||
childScope = block.scope; | ||
|
||
nextNode = previousNode; | ||
do { | ||
nextNode = nextNode.nextSibling; | ||
|
@@ -354,32 +362,19 @@ var ngRepeatDirective = ['$parse', '$animate', function($parse, $animate) { | |
previousNode = getBlockEnd(block); | ||
} else { | ||
// new item which we don't know about | ||
childScope = $scope.$new(); | ||
} | ||
|
||
childScope[valueIdentifier] = value; | ||
if (keyIdentifier) childScope[keyIdentifier] = key; | ||
childScope.$index = index; | ||
childScope.$first = (index === 0); | ||
childScope.$last = (index === (arrayLength - 1)); | ||
childScope.$middle = !(childScope.$first || childScope.$last); | ||
// jshint bitwise: false | ||
childScope.$odd = !(childScope.$even = (index&1) === 0); | ||
// jshint bitwise: true | ||
|
||
if (!block.scope) { | ||
$transclude(childScope, function(clone) { | ||
$transclude(function(clone, scope) { | ||
block.scope = scope; | ||
clone[clone.length++] = document.createComment(' end ngRepeat: ' + expression + ' '); | ||
$animate.enter(clone, null, jqLite(previousNode)); | ||
previousNode = clone; | ||
block.scope = childScope; | ||
// 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; | ||
}); | ||
} | ||
updateScope(block.scope, index); | ||
} | ||
lastBlockMap = nextBlockMap; | ||
}); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm afraid this fix is wrong. See this failing test: https://github.com/vojtajina/angular.js/tree/pr-7565-incorrect-transclusion-scope
I need to investigate this more to figure out some better way how to fix this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I pushed a fix into the https://github.com/vojtajina/angular.js/tree/pr-7565-incorrect-transclusion-scope branch.