Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(57)

Side by Side Diff: third_party/pkg/angular/lib/directive/ng_model_select.dart

Issue 256553002: Revert "Update all Angular libs (run update_all.sh)." (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 part of angular.directive;
2
3 /**
4 * HTML [SELECT] element with angular data-binding if used with
5 * [NgModel].
6 *
7 * The [NgModel] will receive the currently selected item. The binding
8 * is performed on the [OPTION].[value] property. An empty [OPTION].[value] is
9 * treated as null.
10 *
11 * If you the model contains value which does not map to any [OPTION] then a new
12 * unknown [OPTION] is inserted into the list. Once the model points to an
13 * existing [OPTION] the unknown [OPTION] is removed.
14 *
15 * Because [OPTION].[value] attribute is a string, the model is bound to a
16 * string. If there is need to bind to an object then [OptionValue]
17 * should be used.
18 *
19 */
20 @Decorator(
21 selector: 'select[ng-model]')
22 class InputSelect implements AttachAware {
23 final expando = new Expando<OptionValue>();
24 final dom.SelectElement _selectElement;
25 final NodeAttrs _attrs;
26 final NgModel _model;
27 final Scope _scope;
28
29 final dom.OptionElement _unknownOption = new dom.OptionElement();
30 dom.OptionElement _nullOption;
31
32 _SelectMode _mode = new _SelectMode(null, null, null);
33 bool _dirty = false;
34
35 InputSelect(dom.Element this._selectElement, this._attrs, this._model,
36 this._scope) {
37 _unknownOption.value = '?';
38 _nullOption = _selectElement.querySelectorAll('option')
39 .firstWhere((o) => o.value == '', orElse: () => null);
40 }
41
42 attach() {
43 _attrs.observe('multiple', (value) {
44 _mode.destroy();
45 if (value == null) {
46 _model.watchCollection = false;
47 _mode = new _SingleSelectMode(expando, _selectElement, _model,
48 _nullOption, _unknownOption);
49 } else {
50 _model.watchCollection = true;
51 _mode = new _MultipleSelectionMode(expando, _selectElement, _model);
52 }
53 _mode.onModelChange(_model.viewValue);
54 });
55
56 _selectElement.onChange.listen((event) => _mode.onViewChange(event));
57 _model.render = (value) {
58 // TODO(misko): this hack need to delay the rendering until after domRead
59 // because the modelChange reads from the DOM. We should be able to render
60 // without DOM changes.
61 _scope.rootScope.domRead(() {
62 _scope.rootScope.domWrite(() => _mode.onModelChange(value));
63 });
64 };
65 }
66
67 /**
68 * This method invalidates the current state of the selector and forces a
69 * re-rendering of the options using the [Scope.evalAsync].
70 */
71 dirty() {
72 if (!_dirty) {
73 _dirty = true;
74 // TODO(misko): this hack need to delay the rendering until after domRead
75 // because the modelChange reads from the DOM. We should be able to render
76 // without DOM changes.
77 _scope.rootScope.domRead(() {
78 _scope.rootScope.domWrite(() {
79 _dirty = false;
80 _mode.onModelChange(_model.viewValue);
81 });
82 });
83 }
84 }
85 }
86
87 /**
88 * Since the [value] attribute of the [OPTION] can only be a string, Angular
89 * provides [ng-value] which allows binding to any expression.
90 *
91 */
92 @Decorator(selector: 'option', module: NgValue.moduleFactory)
93 class OptionValue implements AttachAware,
94 DetachAware {
95 final InputSelect _inputSelectDirective;
96 final dom.Element _element;
97
98 NgValue _ngValue;
99
100 OptionValue(this._element, this._inputSelectDirective, this._ngValue) {
101 if (_inputSelectDirective != null) {
102 _inputSelectDirective.expando[_element] = this;
103 }
104 }
105
106 attach() {
107 if (_inputSelectDirective != null) _inputSelectDirective.dirty();
108 }
109
110 detach() {
111 if (_inputSelectDirective != null) {
112 _inputSelectDirective.dirty();
113 _inputSelectDirective.expando[_element] = null;
114 }
115 }
116
117 get ngValue => _ngValue.value;
118 }
119
120 class _SelectMode {
121 final Expando<OptionValue> expando;
122 final dom.SelectElement select;
123 final NgModel model;
124
125 _SelectMode(this.expando, this.select, this.model);
126
127 onViewChange(event) {}
128 onModelChange(value) {}
129 destroy() {}
130
131 get _options => select.querySelectorAll('option');
132 _forEachOption(fn, [quiteOnReturn = false]) {
133 for (var i = 0; i < _options.length; i++) {
134 var retValue = fn(_options[i], i);
135 if (quiteOnReturn && retValue != null) return retValue;
136 }
137 return null;
138 }
139 }
140
141 class _SingleSelectMode extends _SelectMode {
142 final dom.OptionElement _unknownOption;
143 final dom.OptionElement _nullOption;
144
145 bool _unknownOptionActive = false;
146
147 _SingleSelectMode(Expando<OptionValue> expando,
148 dom.SelectElement select,
149 NgModel model,
150 this._nullOption,
151 this._unknownOption)
152 : super(expando, select, model) {
153 }
154
155 onViewChange(event) {
156 var i = 0;
157 model.viewValue = _forEachOption((option, _) {
158 if (option.selected) {
159 if (option == _nullOption) return null;
160 assert(expando[option] != null);
161 return expando[option].ngValue;
162 }
163 if (option != _unknownOption && option != _nullOption) i++;
164 }, true);
165 }
166
167 onModelChange(value) {
168 var found = false;
169 _forEachOption((option, i) {
170 if (option == _unknownOption) return;
171 var selected;
172 if (value == null) {
173 selected = option == _nullOption;
174 } else {
175 OptionValue optionValueDirective = expando[option];
176 selected = optionValueDirective == null ?
177 false :
178 optionValueDirective.ngValue == value;
179 }
180 found = found || selected;
181 option.selected = selected;
182 });
183
184 if (!found) {
185 if (!_unknownOptionActive) {
186 select.insertBefore(_unknownOption, select.firstChild);
187 _unknownOption.selected = true;
188 _unknownOptionActive = true;
189 }
190 } else {
191 if (_unknownOptionActive) {
192 _unknownOption.remove();
193 _unknownOptionActive = false;
194 }
195 }
196 }
197 }
198
199 class _MultipleSelectionMode extends _SelectMode {
200 _MultipleSelectionMode(Expando<OptionValue> expando,
201 dom.SelectElement select,
202 NgModel model)
203 : super(expando, select, model);
204
205 onViewChange(event) {
206 var selected = [];
207
208 _forEachOption((o, i) {
209 if (o.selected) selected.add(expando[o].ngValue);
210 });
211 model.viewValue = selected;
212 }
213
214 onModelChange(List selectedValues) {
215 Function fn = (o, i) => o.selected = null;
216
217 if (selectedValues is List) {
218 fn = (o, i) {
219 var selected = expando[o];
220 return selected == null ?
221 false :
222 o.selected = selectedValues.contains(selected.ngValue);
223 };
224 }
225
226 _forEachOption(fn);
227 }
228 }
OLDNEW
« no previous file with comments | « third_party/pkg/angular/lib/directive/ng_model.dart ('k') | third_party/pkg/angular/lib/directive/ng_model_validators.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698