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

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