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

Commit d851e8f

Browse files
committed
fix(select): don't register options when select has no ngModel
When option elements use ngValue, value or interpolated text to set the option value, i.e. when the parent select doesn't have an ngModel, there is no necessity in registering the options with the select controller. The registration was usually not a problem, as the ngModelController is set to a noop controller, so that all further interactions are aborted ($render etc) However, since f02b707 ngValue sets a hashed value inside the option value (to support arbitrary value types). This can cause issues with tests that expect unhashed values. The issue was found in angular-material, which uses select + ngValue to populate mdSelect. POSSIBLE BREAKING CHANGE: Option elements will no longer set their value attribute from their text value when their select element has no ngModel associated. Setting the value is only needed for the select directive to match model values and options. If no ngModel is present, the select directive doesn't need it. This should not affect many applications as the behavior was undocumented and not part of a public API. It also has no effect on the usual HTML5 behavior that sets the select value to the option text if the option does not provide a value attribute.
1 parent 14519f8 commit d851e8f

File tree

2 files changed

+32
-3
lines changed

2 files changed

+32
-3
lines changed

src/ng/directive/select.js

+8-3
Original file line numberDiff line numberDiff line change
@@ -519,11 +519,16 @@ var selectDirective = function() {
519519

520520
function selectPreLink(scope, element, attr, ctrls) {
521521

522-
// if ngModel is not defined, we don't need to do anything
522+
var selectCtrl = ctrls[0];
523523
var ngModelCtrl = ctrls[1];
524-
if (!ngModelCtrl) return;
525524

526-
var selectCtrl = ctrls[0];
525+
// if ngModel is not defined, we don't need to do anything but set the registerOption
526+
// function to noop, so options don't get added internally
527+
if (!ngModelCtrl) {
528+
selectCtrl.registerOption = noop;
529+
return;
530+
}
531+
527532

528533
selectCtrl.ngModelCtrl = ngModelCtrl;
529534

test/ng/directive/selectSpec.js

+24
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,30 @@ describe('select', function() {
136136

137137
});
138138

139+
it('should not add options to the select if ngModel is not present', inject(function($rootScope) {
140+
var scope = $rootScope;
141+
scope.d = 'd';
142+
scope.e = 'e';
143+
scope.f = 'f';
144+
145+
compile('<select>' +
146+
'<option ng-value="\'a\'">alabel</option>' +
147+
'<option value="b">blabel</option>' +
148+
'<option >c</option>' +
149+
'<option ng-value="d">dlabel</option>' +
150+
'<option value="{{e}}">elabel</option>' +
151+
'<option>{{f}}</option>' +
152+
'</select>');
153+
154+
var selectCtrl = element.controller('select');
155+
156+
expect(selectCtrl.hasOption('a')).toBe(false);
157+
expect(selectCtrl.hasOption('b')).toBe(false);
158+
expect(selectCtrl.hasOption('c')).toBe(false);
159+
expect(selectCtrl.hasOption('d')).toBe(false);
160+
expect(selectCtrl.hasOption('e')).toBe(false);
161+
expect(selectCtrl.hasOption('f')).toBe(false);
162+
}));
139163

140164
describe('select-one', function() {
141165

0 commit comments

Comments
 (0)