Skip to content
This repository was archived by the owner on Feb 22, 2018. It is now read-only.

Commit 5af8843

Browse files
committed
refactor(InputSelect): code cleanup
1 parent 7caba3f commit 5af8843

File tree

2 files changed

+59
-63
lines changed

2 files changed

+59
-63
lines changed

lib/directive/ng_model_select.dart

+57-56
Original file line numberDiff line numberDiff line change
@@ -22,35 +22,32 @@ part of angular.directive;
2222
selector: 'select[ng-model]',
2323
visibility: Visibility.CHILDREN)
2424
class InputSelect implements AttachAware {
25-
final expando = new Expando<OptionValue>();
25+
final options = new Expando<OptionValue>();
2626
final dom.SelectElement _selectElement;
2727
final NodeAttrs _attrs;
2828
final NgModel _model;
2929
final Scope _scope;
3030

31-
final dom.OptionElement _unknownOption = new dom.OptionElement();
3231
dom.OptionElement _nullOption;
3332

3433
_SelectMode _mode = new _SelectMode(null, null, null);
3534
bool _dirty = false;
3635

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')
4139
.firstWhere((o) => o.value == '', orElse: () => null);
4240
}
4341

44-
attach() {
42+
void attach() {
4543
_attrs.observe('multiple', (value) {
4644
_mode.destroy();
4745
if (value == null) {
4846
_model.watchCollection = false;
49-
_mode = new _SingleSelectMode(expando, _selectElement, _model,
50-
_nullOption, _unknownOption);
47+
_mode = new _SingleSelectMode(options, _selectElement, _model, _nullOption);
5148
} else {
5249
_model.watchCollection = true;
53-
_mode = new _MultipleSelectionMode(expando, _selectElement, _model);
50+
_mode = new _MultipleSelectionMode(options, _selectElement, _model);
5451
}
5552
_scope.rootScope.domRead(() {
5653
_mode.onModelChange(_model.viewValue);
@@ -72,7 +69,7 @@ class InputSelect implements AttachAware {
7269
* This method invalidates the current state of the selector and forces a
7370
* re-rendering of the options using the [Scope.evalAsync].
7471
*/
75-
dirty() {
72+
void dirty() {
7673
if (!_dirty) {
7774
_dirty = true;
7875
// TODO(misko): this hack need to delay the rendering until after domRead
@@ -93,56 +90,66 @@ class InputSelect implements AttachAware {
9390
* expression for the `option.value` attribute and the model. `Selector: option[ng-value]`
9491
*
9592
* # Example
93+
*
9694
* <select ng-model="robot">
9795
* <option ng-repeat "r in robots" ng-value="r">{{r.name}}</option>
9896
* </select>
9997
*
10098
* Note: See [InputSelect] for the simpler case where `option.value` is a string.
10199
*/
102100
@Decorator(selector: 'option', module: NgValue.module)
103-
class OptionValue implements AttachAware,
104-
DetachAware {
101+
class OptionValue implements AttachAware, DetachAware {
105102
final InputSelect _inputSelectDirective;
106103
final dom.Element _element;
107-
108-
NgValue _ngValue;
104+
final NgValue _ngValue;
109105

110106
OptionValue(this._element, this._inputSelectDirective, this._ngValue) {
111107
if (_inputSelectDirective != null) {
112-
_inputSelectDirective.expando[_element] = this;
108+
_inputSelectDirective.options[_element] = this;
113109
}
114110
}
115111

116-
attach() {
112+
void attach() {
117113
if (_inputSelectDirective != null) _inputSelectDirective.dirty();
118114
}
119115

120-
detach() {
116+
void detach() {
121117
if (_inputSelectDirective != null) {
122118
_inputSelectDirective.dirty();
123-
_inputSelectDirective.expando[_element] = null;
119+
_inputSelectDirective.options[_element] = null;
124120
}
125121
}
126122

127-
get ngValue => _ngValue.value;
123+
dynamic get ngValue => _ngValue.value;
128124
}
129125

130126
class _SelectMode {
131-
final Expando<OptionValue> expando;
127+
final Expando<OptionValue> options;
132128
final dom.SelectElement select;
133129
final NgModel model;
134130

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) {}
136136

137-
onViewChange(event) {}
138-
onModelChange(value) {}
139-
destroy() {}
137+
void destroy() {}
140138

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) {
143143
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;
146153
}
147154
return null;
148155
}
@@ -151,41 +158,35 @@ class _SelectMode {
151158
class _SingleSelectMode extends _SelectMode {
152159
final dom.OptionElement _unknownOption;
153160
final dom.OptionElement _nullOption;
154-
155161
bool _unknownOptionActive = false;
156162

157-
_SingleSelectMode(Expando<OptionValue> expando,
163+
_SingleSelectMode(Expando<OptionValue> options,
158164
dom.SelectElement select,
159165
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);
164169

165-
onViewChange(event) {
166-
var i = 0;
167-
model.viewValue = _forEachOption((option, _) {
170+
void onViewChange(_) {
171+
model.viewValue = _firstOptionWhere((option, _) {
168172
if (option.selected) {
169173
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;
172176
}
173-
if (option != _unknownOption && option != _nullOption) i++;
174-
}, true);
177+
});
175178
}
176179

177-
onModelChange(value) {
178-
var found = false;
180+
void onModelChange(value) {
181+
bool found = false;
179182
_forEachOption((option, i) {
180183
if (option == _unknownOption) return;
181184
var selected;
182185
if (value == null) {
183186
selected = option == _nullOption;
184187
} 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;
189190
}
190191
found = found || selected;
191192
option.selected = selected;
@@ -207,26 +208,26 @@ class _SingleSelectMode extends _SelectMode {
207208
}
208209

209210
class _MultipleSelectionMode extends _SelectMode {
210-
_MultipleSelectionMode(Expando<OptionValue> expando,
211+
_MultipleSelectionMode(Expando<OptionValue> options,
211212
dom.SelectElement select,
212213
NgModel model)
213-
: super(expando, select, model);
214+
: super(options, select, model);
214215

215-
onViewChange(event) {
216+
void onViewChange(_) {
216217
var selected = [];
217218

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);
220221
});
221222
model.viewValue = selected;
222223
}
223224

224-
onModelChange(List selectedValues) {
225-
Function fn = (o, i) => o.selected = null;
225+
void onModelChange(List selectedValues) {
226+
Function fn = (o, _) => o.selected = null;
226227

227228
if (selectedValues is List) {
228229
fn = (o, i) {
229-
var selected = expando[o];
230+
var selected = options[o];
230231
return selected == null ?
231232
false :
232233
o.selected = selectedValues.contains(selected.ngValue);

test/directive/ng_model_select_spec.dart

+2-7
Original file line numberDiff line numberDiff line change
@@ -227,15 +227,10 @@ main() {
227227
_.rootScope.apply();
228228
expect(_.rootElement).toEqualSelect([['?'], 'c3p0', 'r2d2']);
229229

230-
_.rootScope.apply(() {
231-
_.rootScope.context['robot'] = 'r2d2';
232-
});
230+
_.rootScope.apply('robot = "r2d2"');
233231
expect(_.rootElement).toEqualSelect(['c3p0', ['r2d2']]);
234232

235-
236-
_.rootScope.apply(() {
237-
_.rootScope.context['robot'] = "wallee";
238-
});
233+
_.rootScope.apply('robot = "wallee"');
239234
expect(_.rootElement).toEqualSelect([['?'], 'c3p0', 'r2d2']);
240235
});
241236

0 commit comments

Comments
 (0)