@@ -22,35 +22,32 @@ part of angular.directive;
22
22
selector: 'select[ng-model]' ,
23
23
visibility: Visibility .CHILDREN )
24
24
class InputSelect implements AttachAware {
25
- final expando = new Expando <OptionValue >();
25
+ final options = new Expando <OptionValue >();
26
26
final dom.SelectElement _selectElement;
27
27
final NodeAttrs _attrs;
28
28
final NgModel _model;
29
29
final Scope _scope;
30
30
31
- final dom.OptionElement _unknownOption = new dom.OptionElement ();
32
31
dom.OptionElement _nullOption;
33
32
34
33
_SelectMode _mode = new _SelectMode (null , null , null );
35
34
bool _dirty = false ;
36
35
37
- InputSelect (dom.Element this ._selectElement, this ._attrs, this ._model,
38
- this ._scope) {
39
- _unknownOption.value = '?' ;
40
- _nullOption = _selectElement.querySelectorAll ('option' )
36
+ InputSelect (dom.Element this ._selectElement, this ._attrs, this ._model, this ._scope) {
37
+ _nullOption = _selectElement
38
+ .querySelectorAll ('option' )
41
39
.firstWhere ((o) => o.value == '' , orElse: () => null );
42
40
}
43
41
44
- attach () {
42
+ void attach () {
45
43
_attrs.observe ('multiple' , (value) {
46
44
_mode.destroy ();
47
45
if (value == null ) {
48
46
_model.watchCollection = false ;
49
- _mode = new _SingleSelectMode (expando, _selectElement, _model,
50
- _nullOption, _unknownOption);
47
+ _mode = new _SingleSelectMode (options, _selectElement, _model, _nullOption);
51
48
} else {
52
49
_model.watchCollection = true ;
53
- _mode = new _MultipleSelectionMode (expando , _selectElement, _model);
50
+ _mode = new _MultipleSelectionMode (options , _selectElement, _model);
54
51
}
55
52
_scope.rootScope.domRead (() {
56
53
_mode.onModelChange (_model.viewValue);
@@ -72,7 +69,7 @@ class InputSelect implements AttachAware {
72
69
* This method invalidates the current state of the selector and forces a
73
70
* re-rendering of the options using the [Scope.evalAsync] .
74
71
*/
75
- dirty () {
72
+ void dirty () {
76
73
if (! _dirty) {
77
74
_dirty = true ;
78
75
// TODO(misko): this hack need to delay the rendering until after domRead
@@ -93,56 +90,66 @@ class InputSelect implements AttachAware {
93
90
* expression for the `option.value` attribute and the model. `Selector: option[ng-value]`
94
91
*
95
92
* # Example
93
+ *
96
94
* <select ng-model="robot">
97
95
* <option ng-repeat "r in robots" ng-value="r">{{r.name}}</option>
98
96
* </select>
99
97
*
100
98
* Note: See [InputSelect] for the simpler case where `option.value` is a string.
101
99
*/
102
100
@Decorator (selector: 'option' , module: NgValue .module)
103
- class OptionValue implements AttachAware ,
104
- DetachAware {
101
+ class OptionValue implements AttachAware , DetachAware {
105
102
final InputSelect _inputSelectDirective;
106
103
final dom.Element _element;
107
-
108
- NgValue _ngValue;
104
+ final NgValue _ngValue;
109
105
110
106
OptionValue (this ._element, this ._inputSelectDirective, this ._ngValue) {
111
107
if (_inputSelectDirective != null ) {
112
- _inputSelectDirective.expando [_element] = this ;
108
+ _inputSelectDirective.options [_element] = this ;
113
109
}
114
110
}
115
111
116
- attach () {
112
+ void attach () {
117
113
if (_inputSelectDirective != null ) _inputSelectDirective.dirty ();
118
114
}
119
115
120
- detach () {
116
+ void detach () {
121
117
if (_inputSelectDirective != null ) {
122
118
_inputSelectDirective.dirty ();
123
- _inputSelectDirective.expando [_element] = null ;
119
+ _inputSelectDirective.options [_element] = null ;
124
120
}
125
121
}
126
122
127
- get ngValue => _ngValue.value;
123
+ dynamic get ngValue => _ngValue.value;
128
124
}
129
125
130
126
class _SelectMode {
131
- final Expando <OptionValue > expando ;
127
+ final Expando <OptionValue > options ;
132
128
final dom.SelectElement select;
133
129
final NgModel model;
134
130
135
- _SelectMode (this .expando, this .select, this .model);
131
+ _SelectMode (this .options, this .select, this .model);
132
+
133
+ void onViewChange (event) {}
134
+
135
+ void onModelChange (value) {}
136
136
137
- onViewChange (event) {}
138
- onModelChange (value) {}
139
- destroy () {}
137
+ void destroy () {}
140
138
141
- get _options => select.querySelectorAll ('option' );
142
- _forEachOption (fn, [quitOnReturn = false ]) {
139
+ dom.ElementList get _options => select.querySelectorAll ('option' );
140
+
141
+ /// Executes the `callback` on all the options
142
+ void _forEachOption (Function callback) {
143
143
for (var i = 0 ; i < _options.length; i++ ) {
144
- var retValue = fn (_options[i], i);
145
- if (quitOnReturn && retValue != null ) return retValue;
144
+ callback (_options[i], i);
145
+ }
146
+ }
147
+
148
+ /// Executes the `callback` and returns the result of the first one which does not return `null`
149
+ dynamic _firstOptionWhere (Function callback) {
150
+ for (var i = 0 ; i < _options.length; i++ ) {
151
+ var retValue = callback (_options[i], i);
152
+ if (retValue != null ) return retValue;
146
153
}
147
154
return null ;
148
155
}
@@ -151,41 +158,35 @@ class _SelectMode {
151
158
class _SingleSelectMode extends _SelectMode {
152
159
final dom.OptionElement _unknownOption;
153
160
final dom.OptionElement _nullOption;
154
-
155
161
bool _unknownOptionActive = false ;
156
162
157
- _SingleSelectMode (Expando <OptionValue > expando ,
163
+ _SingleSelectMode (Expando <OptionValue > options ,
158
164
dom.SelectElement select,
159
165
NgModel model,
160
- this ._nullOption,
161
- this ._unknownOption)
162
- : super (expando, select, model) {
163
- }
166
+ this ._nullOption)
167
+ : _unknownOption = new dom.OptionElement (value: '?' ),
168
+ super (options, select, model);
164
169
165
- onViewChange (event) {
166
- var i = 0 ;
167
- model.viewValue = _forEachOption ((option, _) {
170
+ void onViewChange (_) {
171
+ model.viewValue = _firstOptionWhere ((option, _) {
168
172
if (option.selected) {
169
173
if (option == _nullOption) return null ;
170
- assert (expando [option] != null );
171
- return expando [option].ngValue;
174
+ assert (options [option] != null );
175
+ return options [option].ngValue;
172
176
}
173
- if (option != _unknownOption && option != _nullOption) i++ ;
174
- }, true );
177
+ });
175
178
}
176
179
177
- onModelChange (value) {
178
- var found = false ;
180
+ void onModelChange (value) {
181
+ bool found = false ;
179
182
_forEachOption ((option, i) {
180
183
if (option == _unknownOption) return ;
181
184
var selected;
182
185
if (value == null ) {
183
186
selected = option == _nullOption;
184
187
} else {
185
- OptionValue optionValueDirective = expando[option];
186
- selected = optionValueDirective == null ?
187
- false :
188
- optionValueDirective.ngValue == value;
188
+ OptionValue optionValue = options[option];
189
+ selected = optionValue == null ? false : optionValue.ngValue == value;
189
190
}
190
191
found = found || selected;
191
192
option.selected = selected;
@@ -207,26 +208,26 @@ class _SingleSelectMode extends _SelectMode {
207
208
}
208
209
209
210
class _MultipleSelectionMode extends _SelectMode {
210
- _MultipleSelectionMode (Expando <OptionValue > expando ,
211
+ _MultipleSelectionMode (Expando <OptionValue > options ,
211
212
dom.SelectElement select,
212
213
NgModel model)
213
- : super (expando , select, model);
214
+ : super (options , select, model);
214
215
215
- onViewChange (event ) {
216
+ void onViewChange (_ ) {
216
217
var selected = [];
217
218
218
- _forEachOption ((o, i ) {
219
- if (o.selected) selected.add (expando [o].ngValue);
219
+ _forEachOption ((o, _ ) {
220
+ if (o.selected) selected.add (options [o].ngValue);
220
221
});
221
222
model.viewValue = selected;
222
223
}
223
224
224
- onModelChange (List selectedValues) {
225
- Function fn = (o, i ) => o.selected = null ;
225
+ void onModelChange (List selectedValues) {
226
+ Function fn = (o, _ ) => o.selected = null ;
226
227
227
228
if (selectedValues is List ) {
228
229
fn = (o, i) {
229
- var selected = expando [o];
230
+ var selected = options [o];
230
231
return selected == null ?
231
232
false :
232
233
o.selected = selectedValues.contains (selected.ngValue);
0 commit comments