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.
PR (#14864)
This commit is contained in:
@@ -519,11 +519,16 @@ var selectDirective = function() {
|
||||
|
||||
function selectPreLink(scope, element, attr, ctrls) {
|
||||
|
||||
// if ngModel is not defined, we don't need to do anything
|
||||
var ngModelCtrl = ctrls[1];
|
||||
if (!ngModelCtrl) return;
|
||||
|
||||
var selectCtrl = ctrls[0];
|
||||
var ngModelCtrl = ctrls[1];
|
||||
|
||||
// if ngModel is not defined, we don't need to do anything but set the registerOption
|
||||
// function to noop, so options don't get added internally
|
||||
if (!ngModelCtrl) {
|
||||
selectCtrl.registerOption = noop;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
selectCtrl.ngModelCtrl = ngModelCtrl;
|
||||
|
||||
|
||||
@@ -136,6 +136,30 @@ describe('select', function() {
|
||||
|
||||
});
|
||||
|
||||
it('should not add options to the select if ngModel is not present', inject(function($rootScope) {
|
||||
var scope = $rootScope;
|
||||
scope.d = 'd';
|
||||
scope.e = 'e';
|
||||
scope.f = 'f';
|
||||
|
||||
compile('<select>' +
|
||||
'<option ng-value="\'a\'">alabel</option>' +
|
||||
'<option value="b">blabel</option>' +
|
||||
'<option >c</option>' +
|
||||
'<option ng-value="d">dlabel</option>' +
|
||||
'<option value="{{e}}">elabel</option>' +
|
||||
'<option>{{f}}</option>' +
|
||||
'</select>');
|
||||
|
||||
var selectCtrl = element.controller('select');
|
||||
|
||||
expect(selectCtrl.hasOption('a')).toBe(false);
|
||||
expect(selectCtrl.hasOption('b')).toBe(false);
|
||||
expect(selectCtrl.hasOption('c')).toBe(false);
|
||||
expect(selectCtrl.hasOption('d')).toBe(false);
|
||||
expect(selectCtrl.hasOption('e')).toBe(false);
|
||||
expect(selectCtrl.hasOption('f')).toBe(false);
|
||||
}));
|
||||
|
||||
describe('select-one', function() {
|
||||
|
||||
|
||||
Reference in New Issue
Block a user