4
4
5
5
var noopNgModelController = { $setViewValue : noop , $render : noop } ;
6
6
7
- function setOptionAsSelected ( optionEl ) {
8
- optionEl . prop ( 'selected' , true ) ; // needed for IE
9
- optionEl . attr ( 'selected' , true ) ;
7
+ function setOptionSelectedStatus ( optionEl , value ) {
8
+ optionEl . prop ( 'selected' , value ) ; // needed for IE
9
+ if ( value ) {
10
+ optionEl . attr ( 'selected' , value ) ;
11
+ } else {
12
+ // Technically, setting the property to null / false is enough to unselect the option
13
+ // However, screenreaders might react to the selected attribute instead, see
14
+ // https://github.com/angular/angular.js/issues/14419
15
+ optionEl . removeAttr ( 'selected' ) ;
16
+ }
10
17
}
11
18
12
19
/**
@@ -49,14 +56,14 @@ var SelectController =
49
56
var unknownVal = self . generateUnknownOptionValue ( val ) ;
50
57
self . unknownOption . val ( unknownVal ) ;
51
58
$element . prepend ( self . unknownOption ) ;
52
- setOptionAsSelected ( self . unknownOption ) ;
59
+ setOptionSelectedStatus ( self . unknownOption , true ) ;
53
60
$element . val ( unknownVal ) ;
54
61
} ;
55
62
56
63
self . updateUnknownOption = function ( val ) {
57
64
var unknownVal = self . generateUnknownOptionValue ( val ) ;
58
65
self . unknownOption . val ( unknownVal ) ;
59
- setOptionAsSelected ( self . unknownOption ) ;
66
+ setOptionSelectedStatus ( self . unknownOption , true ) ;
60
67
$element . val ( unknownVal ) ;
61
68
} ;
62
69
@@ -71,7 +78,7 @@ var SelectController =
71
78
self . selectEmptyOption = function ( ) {
72
79
if ( self . emptyOption ) {
73
80
$element . val ( '' ) ;
74
- setOptionAsSelected ( self . emptyOption ) ;
81
+ setOptionSelectedStatus ( self . emptyOption , true ) ;
75
82
}
76
83
} ;
77
84
@@ -107,7 +114,7 @@ var SelectController =
107
114
// Make sure to remove the selected attribute from the previously selected option
108
115
// Otherwise, screen readers might get confused
109
116
var currentlySelectedOption = $element [ 0 ] . options [ $element [ 0 ] . selectedIndex ] ;
110
- if ( currentlySelectedOption ) currentlySelectedOption . removeAttribute ( 'selected' ) ;
117
+ if ( currentlySelectedOption ) setOptionSelectedStatus ( jqLite ( currentlySelectedOption ) , false ) ;
111
118
112
119
if ( self . hasOption ( value ) ) {
113
120
self . removeUnknownOption ( ) ;
@@ -117,7 +124,7 @@ var SelectController =
117
124
118
125
// Set selected attribute and property on selected option for screen readers
119
126
var selectedOption = $element [ 0 ] . options [ $element [ 0 ] . selectedIndex ] ;
120
- setOptionAsSelected ( jqLite ( selectedOption ) ) ;
127
+ setOptionSelectedStatus ( jqLite ( selectedOption ) , true ) ;
121
128
} else {
122
129
if ( value == null && self . emptyOption ) {
123
130
self . removeUnknownOption ( ) ;
@@ -617,12 +624,8 @@ var selectDirective = function() {
617
624
// So we only modify the selected property if neccessary.
618
625
// Note: this behavior cannot be replicated via unit tests because it only shows in the
619
626
// actual user interface.
620
- if ( ( shouldBeSelected && ! currentlySelected ) ) {
621
- setOptionAsSelected ( jqLite ( option ) ) ;
622
- } else if ( ( ! shouldBeSelected && currentlySelected ) ) {
623
- option . selected = shouldBeSelected ;
624
- // Remove attribute to not confuse screen readers
625
- option . removeAttribute ( 'selected' ) ;
627
+ if ( shouldBeSelected !== currentlySelected ) {
628
+ setOptionSelectedStatus ( jqLite ( option ) , shouldBeSelected ) ;
626
629
}
627
630
628
631
} ) ;
0 commit comments