Skip to content

Commit ed2fd2d

Browse files
petebacondarwinIgorMinar
authored andcommitted
fix(ngRepeat): correctly apply $last if repeating over object
If the $last property is calculated from the original collectionLength on an object and properties starting with $ were filtered out, then $last is never applied and $middle is applied erroniously. Closes angular#1789
1 parent 7c60151 commit ed2fd2d

File tree

2 files changed

+25
-5
lines changed

2 files changed

+25
-5
lines changed

src/ng/directive/ngRepeat.js

+10-5
Original file line numberDiff line numberDiff line change
@@ -92,14 +92,17 @@ var ngRepeatDirective = ngDirective({
9292
scope.$watch(function ngRepeatWatch(scope){
9393
var index, length,
9494
collection = scope.$eval(rhs),
95-
collectionLength = size(collection, true),
96-
childScope,
95+
cursor = iterStartElement, // current position of the node
9796
// Same as lastOrder but it has the current state. It will become the
9897
// lastOrder on the next iteration.
9998
nextOrder = new HashQueueMap(),
99+
arrayLength,
100+
childScope,
100101
key, value, // key/value of iteration
101-
array, last, // last object information {scope, element, index}
102-
cursor = iterStartElement; // current position of the node
102+
array,
103+
last; // last object information {scope, element, index}
104+
105+
103106

104107
if (!isArray(collection)) {
105108
// if object, extract keys, sort them and use to determine order of iteration over obj props
@@ -114,6 +117,8 @@ var ngRepeatDirective = ngDirective({
114117
array = collection || [];
115118
}
116119

120+
arrayLength = array.length;
121+
117122
// we are not using forEach for perf reasons (trying to avoid #call)
118123
for (index = 0, length = array.length; index < length; index++) {
119124
key = (collection === array) ? index : array[index];
@@ -149,7 +154,7 @@ var ngRepeatDirective = ngDirective({
149154
childScope.$index = index;
150155

151156
childScope.$first = (index === 0);
152-
childScope.$last = (index === (collectionLength - 1));
157+
childScope.$last = (index === (arrayLength - 1));
153158
childScope.$middle = !(childScope.$first || childScope.$last);
154159

155160
if (!last) {

test/ng/directive/ngRepeatSpec.js

+15
Original file line numberDiff line numberDiff line change
@@ -293,6 +293,21 @@ describe('ngRepeat', function() {
293293
});
294294

295295

296+
it('should calculate $first, $middle and $last when we filter out properties from an obj', function() {
297+
element = $compile(
298+
'<ul>' +
299+
'<li ng-repeat="(key, val) in items">{{key}}:{{val}}:{{$first}}-{{$middle}}-{{$last}}|</li>' +
300+
'</ul>')(scope);
301+
scope.items = {'misko':'m', 'shyam':'s', 'doug':'d', 'frodo':'f', '$toBeFilteredOut': 'xxxx'};
302+
scope.$digest();
303+
expect(element.text()).
304+
toEqual('doug:d:true-false-false|' +
305+
'frodo:f:false-true-false|' +
306+
'misko:m:false-true-false|' +
307+
'shyam:s:false-false-true|');
308+
});
309+
310+
296311
it('should ignore $ and $$ properties', function() {
297312
element = $compile('<ul><li ng-repeat="i in items">{{i}}|</li></ul>')(scope);
298313
scope.items = ['a', 'b', 'c'];

0 commit comments

Comments
 (0)