Skip to content

Commit 1167a5e

Browse files
committed
fix(ngOptions): always set the 'selected' attribute for selected options
We don't set selected property / attribute on options that are already selected. That happens for example if the browser has automatically selected the first option in a select. In that case, the selected property is set automatically, but the selected attribute is not Closes angular#14115
1 parent ddd7b48 commit 1167a5e

File tree

2 files changed

+29
-18
lines changed

2 files changed

+29
-18
lines changed

src/ng/directive/ngOptions.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -468,13 +468,17 @@ var ngOptionsDirective = ['$compile', '$parse', function($compile, $parse) {
468468
var option = options.getOptionFromViewValue(value);
469469

470470
if (option && !option.disabled) {
471+
// Don't update the option when it is already selected.
472+
// For example, the browser will select the first option by default. In that case,
473+
// most properties are set automatically - except the `selected` attribute.
474+
option.element.setAttribute('selected', 'selected');
475+
471476
if (selectElement[0].value !== option.selectValue) {
472477
removeUnknownOption();
473478
removeEmptyOption();
474479

475480
selectElement[0].value = option.selectValue;
476481
option.element.selected = true;
477-
option.element.setAttribute('selected', 'selected');
478482
}
479483
} else {
480484
if (value === null || providedEmptyOption) {

test/ng/directive/ngOptionsSpec.js

Lines changed: 24 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -298,32 +298,39 @@ describe('ngOptions', function() {
298298

299299
});
300300

301-
iit('should render an array', function() {
302-
scope.metadata = {
303-
currencies: [{
304-
id: 'chf',
305-
symbol: 'CHF'
306-
}, {
307-
id: 'usd',
308-
symbol: 'USD'
309-
}]
310-
};
311-
scope.data = {
312-
selected: 'chf'
313-
};
301+
it('should set the "selected" attribute and property on selected options', function() {
302+
scope.values = [{
303+
id: 'FF0000',
304+
display: 'red'
305+
}, {
306+
id: '0000FF',
307+
display: 'blue'
308+
}];
309+
scope.selected = 'FF0000';
314310

315311
createSelect({
316-
'ng-model': 'data.selected',
317-
'ng-options': 'option.id as option.symbol for option in metadata.currencies'
312+
'ng-model': 'selected',
313+
'ng-options': 'option.id as option.display for option in values'
318314
});
319315
scope.$digest();
320316

321317
var options = element.find('option');
322318
expect(options.length).toEqual(2);
323-
expect(options.eq(0)).toEqualOption('chf', 'CHF');
324-
expect(element.find('option[selected]').length).toBe(1);
319+
expect(options.eq(0)).toEqualOption('FF0000', 'red');
320+
expect(options.eq(1)).toEqualOption('0000FF', 'blue');
321+
322+
expect(options.eq(0)[0].getAttribute('selected')).toBe('selected');
325323
expect(options.eq(0).attr('selected')).toBe('selected');
324+
expect(options.eq(0)[0].selected).toBe(true);
325+
expect(options.eq(0).prop('selected')).toBe(true);
326+
327+
scope.selected = '0000FF';
328+
scope.$digest();
326329

330+
expect(options.eq(1)[0].getAttribute('selected')).toBe('selected');
331+
expect(options.eq(1).attr('selected')).toBe('selected');
332+
expect(options.eq(1)[0].selected).toBe(true);
333+
expect(options.eq(1).prop('selected')).toBe(true);
327334
});
328335

329336
it('should render zero as a valid display value', function() {

0 commit comments

Comments
 (0)