Skip to content

Commit

Permalink
fix(ngRepeat): ensure that the correct (transcluded) scope is used
Browse files Browse the repository at this point in the history
  • Loading branch information
petebacondarwin authored and vojtajina committed May 29, 2014
1 parent d71df9f commit b87e5fc
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 19 deletions.
33 changes: 14 additions & 19 deletions src/ng/directive/ngRepeat.js
Expand Up @@ -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,
Expand All @@ -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;
Expand Down Expand Up @@ -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;
Expand All @@ -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;
});
Expand Down
20 changes: 20 additions & 0 deletions test/ng/directive/ngRepeatSpec.js
Expand Up @@ -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: '<div ng-repeat="a in [1]"><div ng-transclude></div></div>',
scope: {}
}));
});
inject(function($compile, $rootScope) {
$rootScope.val = 'transcluded content';
var element = $compile('<iso><span ng-bind="val"></span></iso>')($rootScope);
$rootScope.$digest();
expect(trim(element.text())).toEqual('transcluded content');
dealoc(element);
});
});

});

describe('ngRepeat animations', function() {
Expand Down

0 comments on commit b87e5fc

Please sign in to comment.