Skip to content

Commit 7d3b9ab

Browse files
fix(ngOptions): update model if selected option is removed
Closes angular#7736
1 parent c693c8b commit 7d3b9ab

File tree

2 files changed

+92
-3
lines changed

2 files changed

+92
-3
lines changed

src/ng/directive/ngOptions.js

+11
Original file line numberDiff line numberDiff line change
@@ -513,7 +513,10 @@ var ngOptionsDirective = ['$compile', '$parse', function($compile, $parse) {
513513

514514
function updateOptions() {
515515

516+
var previousValue = options && selectCtrl.readValue();
517+
516518
options = ngOptions.getOptions();
519+
517520
var groupMap = {};
518521
var currentElement = selectElement[0].firstChild;
519522

@@ -586,6 +589,14 @@ var ngOptionsDirective = ['$compile', '$parse', function($compile, $parse) {
586589
removeExcessElements(currentElement);
587590

588591
ngModelCtrl.$render();
592+
593+
// Check to see if the value has changed due to the update to the options
594+
if(!ngModelCtrl.$isEmpty(previousValue)) {
595+
var nextValue = selectCtrl.readValue();
596+
if (!equals(previousValue, nextValue)) {
597+
ngModelCtrl.$setViewValue(nextValue);
598+
}
599+
}
589600
}
590601

591602
}

test/ng/directive/ngOptionsSpec.js

+81-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
'use strict';
22

3-
describe('ngOptions', function() {
3+
ddescribe('ngOptions', function() {
44

55
var scope, formElement, element, $compile;
66

@@ -22,15 +22,17 @@ describe('ngOptions', function() {
2222
this.addMatchers({
2323
toEqualSelectValue: function(value, multiple) {
2424
var errors = [];
25+
var actual = this.actual.val();
2526

2627
if (multiple) {
2728
value = value.map(function(val) { return hashKey(val); });
29+
actual = actual || [];
2830
} else {
2931
value = hashKey(value);
3032
}
3133

32-
if (!equals(this.actual.val(), value)) {
33-
errors.push('Expected select value "' + this.actual.val() + '" to equal "' + value + '"');
34+
if (!equals(actual, value)) {
35+
errors.push('Expected select value "' + actual + '" to equal "' + value + '"');
3436
}
3537
this.message = function() {
3638
return errors.join('\n');
@@ -1279,6 +1281,82 @@ describe('ngOptions', function() {
12791281
var option = element.find('option').eq(0);
12801282
expect(option).toEqualUnknownOption();
12811283
});
1284+
1285+
1286+
it('should update the model if the selected option is removed', function() {
1287+
scope.values = [{value: 0, label: 'zero'}, {value: 1, label: 'one'}];
1288+
scope.selected = 1;
1289+
createSelect({
1290+
'ng-model': 'selected',
1291+
'ng-options': 'option.value as option.label for option in values'
1292+
});
1293+
expect(element).toEqualSelectValue(1);
1294+
1295+
// Check after initial option update
1296+
scope.$apply(function() {
1297+
scope.values.pop();
1298+
});
1299+
1300+
expect(element.val()).toEqualUnknownValue();
1301+
expect(scope.selected).toEqual(null);
1302+
1303+
// Check after model change
1304+
scope.$apply(function() {
1305+
scope.selected = 0;
1306+
});
1307+
1308+
expect(element).toEqualSelectValue(0);
1309+
1310+
scope.$apply(function() {
1311+
scope.values.pop();
1312+
});
1313+
1314+
expect(element.val()).toEqualUnknownValue();
1315+
expect(scope.selected).toEqual(null);
1316+
});
1317+
1318+
1319+
it('should update the model if all the selected (multiple) options are removed', function() {
1320+
scope.values = [{value: 0, label: 'zero'}, {value: 1, label: 'one'}, {value: 2, label: 'two'}];
1321+
scope.selected = [1, 2];
1322+
createSelect({
1323+
'ng-model': 'selected',
1324+
'multiple': true,
1325+
'ng-options': 'option.value as option.label for option in values'
1326+
});
1327+
1328+
expect(element).toEqualSelectValue([1, 2], true);
1329+
1330+
// Check after initial option update
1331+
scope.$apply(function() {
1332+
scope.values.pop();
1333+
});
1334+
1335+
expect(element).toEqualSelectValue([1], true);
1336+
expect(scope.selected).toEqual([1]);
1337+
1338+
scope.$apply(function() {
1339+
scope.values.pop();
1340+
});
1341+
1342+
expect(element).toEqualSelectValue([], true);
1343+
expect(scope.selected).toEqual([]);
1344+
1345+
// Check after model change
1346+
scope.$apply(function() {
1347+
scope.selected = [0];
1348+
});
1349+
1350+
expect(element).toEqualSelectValue([0], true);
1351+
1352+
scope.$apply(function() {
1353+
scope.values.pop();
1354+
});
1355+
1356+
expect(element).toEqualSelectValue([], true);
1357+
expect(scope.selected).toEqual([]);
1358+
});
1359+
12821360
});
12831361

12841362

0 commit comments

Comments
 (0)