diff --git a/src/ng/directive/ngRepeat.js b/src/ng/directive/ngRepeat.js index 12e0b5dba83d..c72545cf2ca1 100644 --- a/src/ng/directive/ngRepeat.js +++ b/src/ng/directive/ngRepeat.js @@ -211,18 +211,21 @@ var ngRepeatDirective = ['$parse', '$animate', function($parse, $animate) { var NG_REMOVED = '$$NG_REMOVED'; var ngRepeatMinErr = minErr('ngRepeat'); + var nullAliasProperties = {}; - var updateScope = function(scope, index, valueIdentifier, value, keyIdentifier, key, arrayLength) { + var updateScope = function(scope, index, valueIdentifier, value, keyIdentifier, key, arrayLength, aliasAs) { + var aliasRef = aliasAs ? {} : nullAliasProperties; // TODO(perf): generate setters to shave off ~40ms or 1-1.5% 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); + aliasRef.$index = scope.$index = index; + aliasRef.$first = scope.$first = (index === 0); + aliasRef.$last = scope.$last = (index === (arrayLength - 1)); + aliasRef.$middle = scope.$middle = !(scope.$first || scope.$last); // jshint bitwise: false - scope.$odd = !(scope.$even = (index&1) === 0); + aliasRef.$odd = scope.$odd = !(aliasRef.$even = scope.$even = (index&1) === 0); // jshint bitwise: true + if (aliasAs) scope['$' + aliasAs] = aliasRef; }; var getBlockStart = function(block) { @@ -411,7 +414,7 @@ var ngRepeatDirective = ['$parse', '$animate', function($parse, $animate) { $animate.move(getBlockNodes(block.clone), null, jqLite(previousNode)); } previousNode = getBlockEnd(block); - updateScope(block.scope, index, valueIdentifier, value, keyIdentifier, key, collectionLength); + updateScope(block.scope, index, valueIdentifier, value, keyIdentifier, key, collectionLength, aliasAs); } else { // new item which we don't know about $transclude(function ngRepeatTransclude(clone, scope) { @@ -428,7 +431,7 @@ var ngRepeatDirective = ['$parse', '$animate', function($parse, $animate) { // by a directive with templateUrl when its template arrives. block.clone = clone; nextBlockMap[block.id] = block; - updateScope(block.scope, index, valueIdentifier, value, keyIdentifier, key, collectionLength); + updateScope(block.scope, index, valueIdentifier, value, keyIdentifier, key, collectionLength, aliasAs); }); } } diff --git a/test/ng/directive/ngRepeatSpec.js b/test/ng/directive/ngRepeatSpec.js index c63b1faa474f..bd829193e6ba 100644 --- a/test/ng/directive/ngRepeatSpec.js +++ b/test/ng/directive/ngRepeatSpec.js @@ -492,6 +492,43 @@ describe('ngRepeat', function() { return text.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&"); } })); + + it('should expose the index properties using `${{userSpecifiedAliasName}}`', inject(function() { + var expression = '{{item}}-{{$results.' + ['$index', '$first', '$middle', '$last', '$odd', '$even'].join('}}-{{$results.') + '}}:'; + element = $compile( + '
' + + '
' + expression + '
' + + '
')(scope); + + scope.items = ['a','b','c','d','e','f']; + scope.$digest(); + expect(trim(element.text())).toEqual( + 'a-0-true-false-false-false-true:' + + 'b-1-false-true-false-true-false:' + + 'c-2-false-true-false-false-true:' + + 'd-3-false-true-false-true-false:' + + 'e-4-false-true-false-false-true:' + + 'f-5-false-false-true-true-false:'); + + scope.items.shift(); + scope.$digest(); + expect(trim(element.text())).toEqual( + 'b-0-true-false-false-false-true:' + + 'c-1-false-true-false-true-false:' + + 'd-2-false-true-false-false-true:' + + 'e-3-false-true-false-true-false:' + + 'f-4-false-false-true-false-true:'); + })); + + it('should be possible to access the alias inside the loop', inject(function() { + element = $compile( + '
' + + '
{{results[$index]}}
' + + '
')(scope); + scope.items = ['a','b','c','d','e','f']; + scope.$digest(); + expect(trim(element.text())).toEqual('abcdef'); + })); });