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

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

Issue 180843004: Revert revision 33053 (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 6 years, 9 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 /** 3 /**
4 * Ng-model directive is responsible for reading/writing to the model. 4 * Ng-model directive is responsible for reading/writing to the model.
5 * The directive itself is headless. (It does not know how to render or what 5 * The directive itself is headless. (It does not know how to render or what
6 * events to listen for.) It is meant to be used with other directives which 6 * events to listen for.) It is meant to be used with other directives which
7 * provide the rendering and listening capabilities. The directive itself 7 * provide the rendering and listening capabilities. The directive itself
8 * knows how to convert the view-value into model-value and vice versa by 8 * knows how to convert the view-value into model-value and vice versa by
9 * allowing others to register converters (To be implemented). It also 9 * allowing others to register converters (To be implemented). It also
10 * knows how to (in)validate the model and the form in which it is declared 10 * knows how to (in)validate the model and the form in which it is declared
11 * (to be implemented) 11 * (to be implemented)
12 */ 12 */
13 @NgDirective(selector: '[ng-model]') 13 @NgDirective(
14 class NgModel extends NgControl implements NgAttachAware { 14 selector: '[ng-model]')
15 class NgModel extends NgControl {
15 final NgForm _form; 16 final NgForm _form;
16 final AstParser _parser; 17 final dom.Element _element;
18 final Scope _scope;
17 19
18 BoundGetter getter = ([_]) => null; 20 Getter getter = ([_]) => null;
19 BoundSetter setter = (_, [__]) => null; 21 Setter setter = (_, [__]) => null;
20 22
21 var _lastValue;
22 String _exp; 23 String _exp;
23 final _validators = <NgValidatable>[]; 24 String _name;
24 25
25 Watch _removeWatch; 26 final List<_NgModelValidator> _validators = new List<_NgModelValidator>();
27 final Map<String, bool> currentErrors = new Map<String, bool>();
28
29 Function _removeWatch = () => null;
26 bool _watchCollection; 30 bool _watchCollection;
31
27 Function render = (value) => null; 32 Function render = (value) => null;
28 33
29 NgModel(Scope _scope, dom.Element _element, Injector injector, 34 NgModel(this._scope, NodeAttrs attrs, [dom.Element this._element, NgForm this. _form]) {
30 NgForm this._form, this._parser, NodeAttrs attrs) 35 _exp = 'ng-model=${attrs["ng-model"]}';
31 : super(_scope, _element, injector)
32 {
33 _exp = attrs["ng-model"];
34 watchCollection = false; 36 watchCollection = false;
37
38 _form.addControl(this);
39 pristine = true;
35 } 40 }
36 41
37 process(value, [_]) { 42 get element => _element;
38 validate();
39 _scope.rootScope.domWrite(() => render(value));
40 }
41
42 attach() {
43 watchCollection = false;
44 _scope.on('resetNgModel').listen((e) => reset());
45 }
46
47 reset() {
48 untouched = true;
49 modelValue = _lastValue;
50 }
51 43
52 @NgAttr('name') 44 @NgAttr('name')
53 get name => _name; 45 get name => _name;
54 set name(value) { 46 set name(value) {
55 _name = value; 47 _name = value;
56 _parentControl.addControl(this); 48 _form.addControl(this);
57 } 49 }
58 50
59 // TODO(misko): could we get rid of watch collection, and just always watch th e collection?
60 get watchCollection => _watchCollection; 51 get watchCollection => _watchCollection;
61 set watchCollection(value) { 52 set watchCollection(value) {
62 if (_watchCollection == value) return; 53 if (_watchCollection == value) return;
63 _watchCollection = value; 54 _watchCollection = value;
64 if (_removeWatch!=null) _removeWatch.remove(); 55 _removeWatch();
65 if (_watchCollection) { 56 if (_watchCollection) {
66 _removeWatch = _scope.watch( 57 _removeWatch = _scope.$watchCollection((s) => getter(), (value) => render( value), _exp);
67 _parser(_exp, collection: true), 58 } else {
68 (changeRecord, _) { 59 _removeWatch = _scope.$watch((s) => getter(), (value) => render(value), _e xp);
69 var value = changeRecord is CollectionChangeRecord ? changeRecord.it erable: changeRecord;
70 process(value);
71 });
72 } else if (_exp != null) {
73 _removeWatch = _scope.watch(_exp, process);
74 } 60 }
75 } 61 }
76 62
77 // TODO(misko): getters/setters need to go. We need AST here.
78 @NgCallback('ng-model') 63 @NgCallback('ng-model')
79 set model(BoundExpression boundExpression) { 64 set model(BoundExpression boundExpression) {
80 getter = boundExpression; 65 getter = boundExpression;
81 setter = boundExpression.assign; 66 setter = boundExpression.assign;
82
83 _scope.rootScope.runAsync(() {
84 _lastValue = modelValue;
85 });
86 } 67 }
87 68
88 // TODO(misko): right now viewValue and modelValue are the same, 69 // TODO(misko): right now viewValue and modelValue are the same,
89 // but this needs to be changed to support converters and form validation 70 // but this needs to be changed to support converters and form validation
90 get viewValue => modelValue; 71 get viewValue => modelValue;
91 set viewValue(value) => modelValue = value; 72 set viewValue(value) => modelValue = value;
92 73
93 get modelValue => getter(); 74 get modelValue => getter();
94 set modelValue(value) => setter(value); 75 set modelValue(value) => setter(value);
95 76
96 get validators => _validators; 77 get validators => _validators;
97 78
98 /** 79 /**
99 * Executes a validation on the form against each of the validation present on the model. 80 * Executes a validation on the form against each of the validation present on the model.
100 */ 81 */
101 validate() { 82 validate() {
102 if (validators.isNotEmpty) { 83 if(validators.length > 0) {
103 validators.forEach((validator) { 84 validators.forEach((validator) {
104 setValidity(validator.name, validator.isValid(viewValue)); 85 setValidity(validator.name, validator.isValid());
105 }); 86 });
106 } else { 87 } else {
107 valid = true; 88 valid = true;
108 } 89 }
109 } 90 }
110 91
111 setValidity(String name, bool valid) { 92 /**
112 this.updateControlValidity(this, name, valid); 93 * Sets the validity status of the given errorType on the model. Depending on if
94 * valid or invalid, the matching CSS classes will be added/removed on the inp ut
95 * element associated with the model. If any errors exist on the model then in valid
96 * will be set to true otherwise valid will be set to true.
97 *
98 * * [errorType] - The name of the error (e.g. required, url, number, etc...).
99 * * [isValid] - Whether or not the given error is valid or not (false would m ean the error is real).
100 */
101 setValidity(String errorType, bool isValid) {
102 if(isValid) {
103 if(currentErrors.containsKey(errorType)) {
104 currentErrors.remove(errorType);
105 }
106 if(valid != true && currentErrors.isEmpty) {
107 valid = true;
108 }
109 } else if(!currentErrors.containsKey(errorType)) {
110 currentErrors[errorType] = true;
111 invalid = true;
112 }
113
114 if(_form != null) {
115 _form.setValidity(this, errorType, isValid);
116 }
113 } 117 }
114 118
115 /** 119 /**
116 * Registers a validator into the model to consider when running validate(). 120 * Registers a validator into the model to consider when running validate().
117 */ 121 */
118 addValidator(NgValidatable v) { 122 addValidator(_NgModelValidator v) {
119 validators.add(v); 123 validators.add(v);
120 validate(); 124 validate();
121 } 125 }
122 126
123 /** 127 /**
124 * De-registers a validator from the model. 128 * De-registers a validator from the model.
125 */ 129 */
126 removeValidator(NgValidatable v) { 130 removeValidator(_NgModelValidator v) {
127 validators.remove(v); 131 validators.remove(v);
128 validate(); 132 validate();
129 } 133 }
134
135 /**
136 * Removes the model from the control/form.
137 */
138 destroy() {
139 _form.removeControl(this);
140 }
130 } 141 }
131 142
132 /** 143 /**
133 * Usage: 144 * Usage:
134 * 145 *
135 * <input type="checkbox" ng-model="flag"> 146 * <input type="checkbox" ng-model="flag">
136 * 147 *
137 * This creates a two way databinding between the boolean expression specified 148 * This creates a two way databinding between the boolean expression specified i n
138 * in ng-model and the checkbox input element in the DOM.  If the ng-model value 149 * ng-model and the checkbox input element in the DOM.  If the ng-model value is
139 * is falsy (i.e. one of `false`, `null`, and `0`), then the checkbox is 150 * falsy (i.e. one of `false`, `null`, and `0`), then the checkbox is unchecked.
140 * unchecked. Otherwise, it is checked.  Likewise, when the checkbox is checked, 151 * Otherwise, it is checked.  Likewise, when the checkbox is checked, the model
141 * the model value is set to true. When unchecked, it is set to false. 152 * value is set to true. When unchecked, it is set to false.
153 *
154 * The AngularJS style ng-true-value / ng-false-value is not supported.
142 */ 155 */
143 @NgDirective(selector: 'input[type=checkbox][ng-model]') 156 @NgDirective(selector: 'input[type=checkbox][ng-model]')
144 class InputCheckboxDirective { 157 class InputCheckboxDirective {
145 final dom.InputElement inputElement; 158 dom.InputElement inputElement;
146 final NgModel ngModel; 159 NgModel ngModel;
147 final NgTrueValue ngTrueValue; 160 Scope scope;
148 final NgFalseValue ngFalseValue;
149 final Scope scope;
150 161
151 InputCheckboxDirective(dom.Element this.inputElement, this.ngModel, 162 InputCheckboxDirective(dom.Element this.inputElement, this.ngModel, this.scope ) {
152 this.scope, this.ngTrueValue, this.ngFalseValue) {
153 ngModel.render = (value) { 163 ngModel.render = (value) {
154 inputElement.checked = ngTrueValue.isValue(inputElement, value); 164 inputElement.checked = value == null ? false : toBool(value);
155 }; 165 };
156 inputElement.onChange.listen((value) { 166 inputElement.onChange.listen((value) {
157 ngModel.dirty = true; 167 scope.$apply(() => ngModel.viewValue = inputElement.checked);
158 ngModel.viewValue = inputElement.checked
159 ? ngTrueValue.readValue(inputElement)
160 : ngFalseValue.readValue(inputElement);
161 }); 168 });
162 } 169 }
163 } 170 }
164 171
165 /** 172 /**
166 * Usage: 173 * Usage:
167 * 174 *
168 * <input type="text|url|password|email" ng-model="myModel"> 175 * <input type="text|number|url|password|email" ng-model="myModel">
169 * <textarea ng-model="myModel"></textarea> 176 * <textarea ng-model="myModel"></textarea>
170 * 177 *
171 * This creates a two-way binding between any string-based input element 178 * This creates a two-way binding between any string-based input element
172 * (both <input> and <textarea>) so long as the ng-model attribute is 179 * (both <input> and <textarea>) so long as the ng-model attribute is
173 * present on the input element. Whenever the value of the input element 180 * present on the input element. Whenever the value of the input element
174 * changes then the matching model property on the scope will be updated 181 * changes then the matching model property on the scope will be updated
175 * as well as the other way around (when the scope property is updated). 182 * as well as the other way around (when the scope property is updated).
176 * 183 *
177 */ 184 */
178 @NgDirective(selector: 'textarea[ng-model]') 185 @NgDirective(selector: 'textarea[ng-model]')
179 @NgDirective(selector: 'input[type=text][ng-model]') 186 @NgDirective(selector: 'input[type=text][ng-model]')
180 @NgDirective(selector: 'input[type=password][ng-model]') 187 @NgDirective(selector: 'input[type=password][ng-model]')
181 @NgDirective(selector: 'input[type=url][ng-model]') 188 @NgDirective(selector: 'input[type=url][ng-model]')
182 @NgDirective(selector: 'input[type=email][ng-model]') 189 @NgDirective(selector: 'input[type=email][ng-model]')
183 @NgDirective(selector: 'input[type=search][ng-model]') 190 @NgDirective(selector: 'input[type=number][ng-model]')
184 class InputTextLikeDirective { 191 class InputTextLikeDirective {
185 final dom.Element inputElement; 192 dom.Element inputElement;
186 final NgModel ngModel; 193 NgModel ngModel;
187 final Scope scope; 194 Scope scope;
188 String _inputType; 195 String _inputType;
189 196
190 get typedValue => (inputElement as dynamic).value; 197 get typedValue => (inputElement as dynamic).value;
191 set typedValue(value) => (inputElement as dynamic).value = (value == null) ? 198 set typedValue(value) => (inputElement as dynamic).value = (value == null) ? ' ' : value.toString();
192 '' :
193 value.toString();
194 199
195 InputTextLikeDirective(this.inputElement, this.ngModel, this.scope) { 200 InputTextLikeDirective(dom.Element this.inputElement, NgModel this.ngModel, Sc ope this.scope) {
196 ngModel.render = (value) { 201 ngModel.render = (value) {
197 if (value == null) value = ''; 202 if (value == null) value = '';
198 203
199 var currentValue = typedValue; 204 var currentValue = typedValue;
200 if (value != currentValue && !(value is num && currentValue is num && 205 if (value != currentValue && !(value is num && currentValue is num && valu e.isNaN && currentValue.isNaN)) {
201 value.isNaN && currentValue.isNaN)) {
202 typedValue = value; 206 typedValue = value;
203 } 207 }
204 }; 208 };
205 inputElement 209 inputElement.onChange.listen(relaxFnArgs(processValue));
206 ..onChange.listen(processValue) 210 inputElement.onKeyDown.listen((e) {
207 ..onInput.listen(processValue) 211 new async.Timer(Duration.ZERO, processValue);
208 ..onBlur.listen((e) { 212 scope.$skipAutoDigest();
209 if (ngModel.touched == null || ngModel.touched == false) { 213 });
210 ngModel.touched = true;
211 }
212 });
213 }
214
215 processValue([_]) {
216 var value = typedValue;
217 if (value != ngModel.viewValue) {
218 ngModel.dirty = true;
219 ngModel.viewValue = value;
220 }
221 ngModel.validate();
222 }
223 }
224
225 /**
226 * Usage:
227 *
228 * <input type="number|range" ng-model="myModel">
229 *
230 * Model:
231 *
232 * num myModel;
233 *
234 * This creates a two-way binding between the input and the named model property
235 * (e.g., myModel in the example above). When processing the input, its value is
236 * read as a [num], via the [dom.InputElement.valueAsNumber] field. If the input
237 * text does not represent a number, then the model is appropriately set to
238 * [double.NAN]. Setting the model property to [null] will clear the input.
239 * Setting the model to [double.NAN] will have no effect (input will be left
240 * unchanged).
241 */
242 @NgDirective(selector: 'input[type=number][ng-model]')
243 @NgDirective(selector: 'input[type=range][ng-model]')
244 class InputNumberLikeDirective {
245 final dom.InputElement inputElement;
246 final NgModel ngModel;
247 final Scope scope;
248
249 num get typedValue => inputElement.valueAsNumber;
250 void set typedValue(num value) {
251 // [chalin, 2014-02-16] This post
252 // http://lists.whatwg.org/pipermail/whatwg-whatwg.org/2010-January/024829.h tml
253 // suggests that setting `valueAsNumber` to null should clear the field, but
254 // it does not. [TODO: put BUG/ISSUE number here]. We implement a
255 // workaround by setting `value`. Clean-up once the bug is fixed.
256 if (value == null) {
257 inputElement.value = null;
258 } else {
259 inputElement.valueAsNumber = value;
260 }
261 }
262
263 InputNumberLikeDirective(dom.Element this.inputElement, this.ngModel, this.sco pe) {
264 ngModel.render = (value) {
265 if (value != typedValue
266 && (value == null || value is num && !value.isNaN)) {
267 typedValue = value;
268 }
269 };
270 inputElement
271 ..onChange.listen(relaxFnArgs(processValue))
272 ..onInput.listen(relaxFnArgs(processValue));
273 } 214 }
274 215
275 processValue() { 216 processValue() {
276 num value = typedValue; 217 ngModel.validate();
218 var value = typedValue;
277 if (value != ngModel.viewValue) { 219 if (value != ngModel.viewValue) {
278 ngModel.dirty = true; 220 scope.$apply(() => ngModel.viewValue = value);
279 scope.eval(() => ngModel.viewValue = value);
280 } 221 }
281 ngModel.validate();
282 } 222 }
283 } 223 }
284 224
285 class _UidCounter { 225 class _UidCounter {
286 static final int CHAR_0 = "0".codeUnitAt(0); 226 static final int CHAR_0 = "0".codeUnitAt(0);
287 static final int CHAR_9 = "9".codeUnitAt(0); 227 static final int CHAR_9 = "9".codeUnitAt(0);
288 static final int CHAR_A = "A".codeUnitAt(0); 228 static final int CHAR_A = "A".codeUnitAt(0);
289 static final int CHAR_Z = "Z".codeUnitAt(0); 229 static final int CHAR_Z = "Z".codeUnitAt(0);
290 List charCodes = [CHAR_0, CHAR_0, CHAR_0]; 230 List charCodes = [CHAR_0, CHAR_0, CHAR_0];
291 231
292 String next() { 232 String next() {
293 for (int i = charCodes.length - 1; i >= 0; i--) { 233 for (int i = charCodes.length-1; i >= 0; i--) {
294 int code = charCodes[i]; 234 int code = charCodes[i];
295 if (code == CHAR_9) { 235 if (code == CHAR_9) {
296 charCodes[i] = CHAR_A; 236 charCodes[i] = CHAR_A;
297 return new String.fromCharCodes(charCodes); 237 return new String.fromCharCodes(charCodes);
298 } else if (code == CHAR_Z) { 238 } else if (code == CHAR_Z) {
299 charCodes[i] = CHAR_0; 239 charCodes[i] = CHAR_0;
300 } else { 240 } else {
301 charCodes[i] = code + 1; 241 charCodes[i] = code + 1;
302 return new String.fromCharCodes(charCodes); 242 return new String.fromCharCodes(charCodes);
303 } 243 }
304 } 244 }
305 charCodes.insert(0, CHAR_0); 245 charCodes.insert(0, CHAR_0);
306 return new String.fromCharCodes(charCodes); 246 return new String.fromCharCodes(charCodes);
307 } 247 }
308 } 248 }
309 249
310 final _uidCounter = new _UidCounter(); 250 final _uidCounter = new _UidCounter();
311 251
312 /**
313 * Use `ng-value` directive with `<input type="radio">` or `<option>` to
314 * allow binding to values other then strings. This is needed since the
315 * `value` attribute on DOM element `<input type="radio" value="foo">` can
316 * only be a string. With `ng-value` one can bind to any object.
317 */
318 @NgDirective(selector: '[ng-value]')
319 class NgValue {
320 final dom.Element element;
321 @NgOneWay('ng-value')
322 var value;
323
324 NgValue(this.element);
325
326 readValue(dom.Element element) {
327 assert(this.element == null || element == this.element);
328 return this.element == null ? (element as dynamic).value : value;
329 }
330 }
331
332 /**
333 * `ng-true-value` allows you to select any expression to be set to
334 * `ng-model` when checkbox is selected on `<input type="checkbox">`.
335 */
336 @NgDirective(selector: '[ng-true-value]')
337 class NgTrueValue {
338 final dom.Element element;
339 @NgOneWay('ng-true-value')
340 var value;
341
342 NgTrueValue(this.element);
343
344 readValue(dom.Element element) {
345 assert(this.element == null || element == this.element);
346 return this.element == null ? true : value;
347 }
348
349 isValue(dom.Element element, value) {
350 assert(this.element == null || element == this.element);
351 return this.element == null ? toBool(value) : value == this.value;
352 }
353 }
354
355 /**
356 * `ng-false-value` allows you to select any expression to be set to
357 * `ng-model` when checkbox is deselected<input type="checkbox">`.
358 */
359 @NgDirective(selector: '[ng-false-value]')
360 class NgFalseValue {
361 final dom.Element element;
362 @NgOneWay('ng-false-value')
363 var value;
364
365 NgFalseValue(this.element);
366
367 readValue(dom.Element element) {
368 assert(this.element == null || element == this.element);
369 return this.element == null ? false : value;
370 }
371 }
372 252
373 /** 253 /**
374 * Usage: 254 * Usage:
375 * 255 *
376 * <input type="radio" ng-model="category"> 256 * <input type="radio" ng-model="category">
377 * 257 *
378 * This creates a two way databinding between the expression specified in 258 * This creates a two way databinding between the expression specified in
379 * ng-model and the range input elements in the DOM.  If the ng-model value is 259 * ng-model and the range input elements in the DOM.  If the ng-model value is
380 * set to a value not corresponding to one of the radio elements, then none of 260 * set to a value not corresponding to one of the radio elements, then none of
381 * the radio elements will be check. Otherwise, only the corresponding input 261 * the radio elements will be check. Otherwise, only the corresponding input
382 * element in the group is checked. Likewise, when a radio button element is 262 * element in the group is checked. Likewise, when a radio button element is
383 * checked, the model is updated with its value. Radio buttons that have a 263 * checked, the model is updated with its value. Radio buttons that have a
384 * `name` attribute are left alone. Those that are missing the attribute will 264 * `name` attribute are left alone. Those that are missing the attribute will
385 * have a unique `name` assigned to them. This sequence goes `001`, `001`, ... 265 * have a unique `name` assigned to them. This sequence goes `001`, `001`, ...
386 * `009`, `00A`, `00Z`, `010`, … and so on using more than 3 characters for the 266 * `009`, `00A`, `00Z`, `010`, … and so on using more than 3 characters for the
387 * name when the counter overflows. 267 * name when the counter overflows.
388 */ 268 */
389 @NgDirective(selector: 'input[type=radio][ng-model]') 269 @NgDirective(selector: 'input[type=radio][ng-model]')
390 class InputRadioDirective { 270 class InputRadioDirective {
391 final dom.RadioButtonInputElement radioButtonElement; 271 dom.RadioButtonInputElement radioButtonElement;
392 final NgModel ngModel; 272 NgModel ngModel;
393 final NgValue ngValue; 273 Scope scope;
394 final Scope scope;
395 274
396 InputRadioDirective(dom.Element this.radioButtonElement, this.ngModel, 275 InputRadioDirective(dom.Element this.radioButtonElement, this.ngModel,
397 this.scope, this.ngValue, NodeAttrs attrs) { 276 this.scope, NodeAttrs attrs) {
398 // If there's no "name" set, we'll set a unique name. This ensures 277 // If there's no "name" set, we'll set a unique name. This ensures
399 // less surprising behavior about which radio buttons are grouped together. 278 // less surprising behavior about which radio buttons are grouped together.
400 if (attrs['name'] == '' || attrs['name'] == null) { 279 if (attrs['name'] == '' || attrs['name'] == null) {
401 attrs["name"] = _uidCounter.next(); 280 attrs["name"] = _uidCounter.next();
402 } 281 }
403 ngModel.render = (value) { 282 ngModel.render = (String value) {
404 radioButtonElement.checked = (value == ngValue.readValue(radioButtonElemen t)); 283 radioButtonElement.checked = (value == radioButtonElement.value);
405 }; 284 };
406 radioButtonElement.onClick.listen((_) { 285 radioButtonElement.onClick.listen((_) {
407 if (radioButtonElement.checked) { 286 if (radioButtonElement.checked) {
408 ngModel.dirty = true; 287 scope.$apply(() => ngModel.viewValue = radioButtonElement.value);
409 ngModel.viewValue = ngValue.readValue(radioButtonElement);
410 } 288 }
411 }); 289 });
412 } 290 }
413 } 291 }
414 292
415 /** 293 /**
416 * Usage (span could be replaced with any element which supports text content, s uch as `p`): 294 * Usage (span could be replaced with any element which supports text content, s uch as `p`):
417 * 295 *
418 * <span contenteditable= ng-model="name"> 296 * <span contenteditable= ng-model="name">
419 * 297 *
420 * This creates a two way databinding between the expression specified in 298 * This creates a two way databinding between the expression specified in
421 * ng-model and the html element in the DOM.  If the ng-model value is 299 * ng-model and the html element in the DOM.  If the ng-model value is
422 * `null`, it is treated as equivalent to the empty string for rendering 300 * `null`, it is treated as equivalent to the empty string for rendering
423 * purposes. 301 * purposes.
424 */ 302 */
425 @NgDirective(selector: '[contenteditable][ng-model]') 303 @NgDirective(selector: '[contenteditable][ng-model]')
426 class ContentEditableDirective extends InputTextLikeDirective { 304 class ContentEditableDirective extends InputTextLikeDirective {
427 ContentEditableDirective(dom.Element inputElement, NgModel ngModel, 305 ContentEditableDirective(dom.Element inputElement, NgModel ngModel, Scope scop e):
428 Scope scope) 306 super(inputElement, ngModel, scope);
429 : super(inputElement, ngModel, scope);
430 307
431 // The implementation is identical to InputTextLikeDirective but use innerHtml instead of value 308 // The implementation is identical to InputTextLikeDirective but use innerHtml instead of value
432 get typedValue => (inputElement as dynamic).innerHtml; 309 get typedValue => (inputElement as dynamic).innerHtml;
433 set typedValue(String value) => 310 set typedValue(String value) => (inputElement as dynamic).innerHtml = (value = = null) ? '' : value;
434 (inputElement as dynamic).innerHtml = (value == null) ? '' : value;
435 } 311 }
OLDNEW
« no previous file with comments | « third_party/pkg/angular/lib/directive/ng_include.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