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

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

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

Powered by Google App Engine
This is Rietveld 408576698