From b87e5fc0920915991122ba5dac87b619847b3568 Mon Sep 17 00:00:00 2001 From: Peter Bacon Darwin Date: Fri, 23 May 2014 11:45:03 +0100 Subject: [PATCH] fix(ngRepeat): ensure that the correct (transcluded) scope is used --- src/ng/directive/ngRepeat.js | 33 +++++++++++++------------------ test/ng/directive/ngRepeatSpec.js | 20 +++++++++++++++++++ 2 files changed, 34 insertions(+), 19 deletions(-) diff --git a/src/ng/directive/ngRepeat.js b/src/ng/directive/ngRepeat.js index 5f977ae694e9..972cd0ea2ced 100644 --- a/src/ng/directive/ngRepeat.js +++ b/src/ng/directive/ngRepeat.js @@ -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 + }; if (isArrayLike(collection)) { collectionKeys = collection; @@ -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,25 +362,11 @@ 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. @@ -380,6 +374,7 @@ var ngRepeatDirective = ['$parse', '$animate', function($parse, $animate) { nextBlockMap[block.id] = block; }); } + updateScope(block.scope, index); } lastBlockMap = nextBlockMap; }); diff --git a/test/ng/directive/ngRepeatSpec.js b/test/ng/directive/ngRepeatSpec.js index 0cc847e66634..fd8f216a524e 100644 --- a/test/ng/directive/ngRepeatSpec.js +++ b/test/ng/directive/ngRepeatSpec.js @@ -1175,6 +1175,26 @@ describe('ngRepeat and transcludes', function() { dealoc(element); }); }); + + + it('should use the correct transcluded scope', function() { + module(function($compileProvider) { + $compileProvider.directive('iso', valueFn({ + restrict: 'E', + transclude: true, + template: '
', + scope: {} + })); + }); + inject(function($compile, $rootScope) { + $rootScope.val = 'transcluded content'; + var element = $compile('')($rootScope); + $rootScope.$digest(); + expect(trim(element.text())).toEqual('transcluded content'); + dealoc(element); + }); + }); + }); describe('ngRepeat animations', function() {