Skip to content
This repository was archived by the owner on Apr 12, 2024. It is now read-only.

Commit 476c877

Browse files
committed
fix(select): respect tracking expression when shallow watching arrays of objects in ngOptions
ngOptions does not use the tracking expression when shallow watching array elements passed in to ngOptions. This is a problem if the elements passed in to ngOptions are generated on the fly and while the array elements identical in value, they are different instances; this leads to infinite digest loops. This change attempts to rectify the situation by shallow watching an array of trackFn(values) rather than the array of values themselves. Closes #9464
1 parent 07d6242 commit 476c877

File tree

2 files changed

+41
-2
lines changed

2 files changed

+41
-2
lines changed

src/ng/directive/select.js

+18-2
Original file line numberDiff line numberDiff line change
@@ -403,7 +403,23 @@ var selectDirective = ['$compile', '$parse', function($compile, $parse) {
403403

404404
ctrl.$render = render;
405405

406-
scope.$watchCollection(valuesFn, render);
406+
if (trackFn) {
407+
scope.$watchCollection(function() {
408+
var locals = {},
409+
values = valuesFn(scope);
410+
if (values) {
411+
var trackers = new Array(values.length);
412+
for (var i = 0, ii = values.length; i < ii; i++) {
413+
trackers[i] = trackFn(scope, locals);
414+
}
415+
416+
return trackers;
417+
}
418+
}, render);
419+
} else {
420+
scope.$watchCollection(valuesFn, render);
421+
}
422+
407423
scope.$watchCollection(function () {
408424
var locals = {},
409425
values = valuesFn(scope);
@@ -570,7 +586,7 @@ var selectDirective = ['$compile', '$parse', function($compile, $parse) {
570586

571587
// if it's a null option
572588
if (option.id === '' && nullOption) {
573-
// put back the pre-compiled element
589+
// put back the pre-compwailed element
574590
element = nullOption;
575591
} else {
576592
// jQuery(v1.4.2) Bug: We should be able to chain the method calls, but

test/ng/directive/selectSpec.js

+23
Original file line numberDiff line numberDiff line change
@@ -1130,6 +1130,29 @@ describe('select', function() {
11301130
expect(element.val()).toEqual('?');
11311131
expect(countSelected()).toEqual(1);
11321132
});
1133+
1134+
it('should respect trackexpr when working with arrays of objects', function() {
1135+
var elementCount = 5;
1136+
1137+
createSelect({
1138+
'ng-model':'selected',
1139+
'ng-options':'v as v.label for v in makeValues() track by v.code'
1140+
});
1141+
1142+
scope.$apply(function() {
1143+
scope.makeValues = function() {
1144+
var values = [];
1145+
for (var i = 0; i < elementCount; i++) {
1146+
values.push({label: 'Value = ' + i, code: i});
1147+
}
1148+
1149+
return values;
1150+
};
1151+
scope.selected = {label: 'Value = 1', code: 1};
1152+
});
1153+
1154+
expect(element.find('option').length).toEqual(elementCount);
1155+
});
11331156
});
11341157

11351158

0 commit comments

Comments
 (0)