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

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

Issue 180873006: Update the Angular/DI tests to latest from github. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Review feedback 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( 13 @NgDirective(selector: '[ng-model]')
14 selector: '[ng-model]') 14 class NgModel extends NgControl implements NgAttachAware {
15 class NgModel extends NgControl {
16 final NgForm _form; 15 final NgForm _form;
17 final dom.Element _element; 16 final AstParser _parser;
18 final Scope _scope;
19 17
20 Getter getter = ([_]) => null; 18 BoundGetter getter = ([_]) => null;
21 Setter setter = (_, [__]) => null; 19 BoundSetter setter = (_, [__]) => null;
22 20
21 var _lastValue;
23 String _exp; 22 String _exp;
24 String _name; 23 final _validators = <NgValidatable>[];
25 24
26 final List<_NgModelValidator> _validators = new List<_NgModelValidator>(); 25 Watch _removeWatch;
27 final Map<String, bool> currentErrors = new Map<String, bool>();
28
29 Function _removeWatch = () => null;
30 bool _watchCollection; 26 bool _watchCollection;
31
32 Function render = (value) => null; 27 Function render = (value) => null;
33 28
34 NgModel(this._scope, NodeAttrs attrs, [dom.Element this._element, NgForm this. _form]) { 29 NgModel(Scope _scope, dom.Element _element, Injector injector,
35 _exp = 'ng-model=${attrs["ng-model"]}'; 30 NgForm this._form, this._parser, NodeAttrs attrs)
31 : super(_scope, _element, injector)
32 {
33 _exp = attrs["ng-model"];
36 watchCollection = false; 34 watchCollection = false;
37
38 _form.addControl(this);
39 pristine = true;
40 } 35 }
41 36
42 get element => _element; 37 process(value, [_]) {
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 }
43 51
44 @NgAttr('name') 52 @NgAttr('name')
45 get name => _name; 53 get name => _name;
46 set name(value) { 54 set name(value) {
47 _name = value; 55 _name = value;
48 _form.addControl(this); 56 _parentControl.addControl(this);
49 } 57 }
50 58
59 // TODO(misko): could we get rid of watch collection, and just always watch th e collection?
51 get watchCollection => _watchCollection; 60 get watchCollection => _watchCollection;
52 set watchCollection(value) { 61 set watchCollection(value) {
53 if (_watchCollection == value) return; 62 if (_watchCollection == value) return;
54 _watchCollection = value; 63 _watchCollection = value;
55 _removeWatch(); 64 if (_removeWatch!=null) _removeWatch.remove();
56 if (_watchCollection) { 65 if (_watchCollection) {
57 _removeWatch = _scope.$watchCollection((s) => getter(), (value) => render( value), _exp); 66 _removeWatch = _scope.watch(
58 } else { 67 _parser(_exp, collection: true),
59 _removeWatch = _scope.$watch((s) => getter(), (value) => render(value), _e xp); 68 (changeRecord, _) {
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);
60 } 74 }
61 } 75 }
62 76
77 // TODO(misko): getters/setters need to go. We need AST here.
63 @NgCallback('ng-model') 78 @NgCallback('ng-model')
64 set model(BoundExpression boundExpression) { 79 set model(BoundExpression boundExpression) {
65 getter = boundExpression; 80 getter = boundExpression;
66 setter = boundExpression.assign; 81 setter = boundExpression.assign;
82
83 _scope.rootScope.runAsync(() {
84 _lastValue = modelValue;
85 });
67 } 86 }
68 87
69 // TODO(misko): right now viewValue and modelValue are the same, 88 // TODO(misko): right now viewValue and modelValue are the same,
70 // but this needs to be changed to support converters and form validation 89 // but this needs to be changed to support converters and form validation
71 get viewValue => modelValue; 90 get viewValue => modelValue;
72 set viewValue(value) => modelValue = value; 91 set viewValue(value) => modelValue = value;
73 92
74 get modelValue => getter(); 93 get modelValue => getter();
75 set modelValue(value) => setter(value); 94 set modelValue(value) => setter(value);
76 95
77 get validators => _validators; 96 get validators => _validators;
78 97
79 /** 98 /**
80 * Executes a validation on the form against each of the validation present on the model. 99 * Executes a validation on the form against each of the validation present on the model.
81 */ 100 */
82 validate() { 101 validate() {
83 if(validators.length > 0) { 102 if (validators.isNotEmpty) {
84 validators.forEach((validator) { 103 validators.forEach((validator) {
85 setValidity(validator.name, validator.isValid()); 104 setValidity(validator.name, validator.isValid(viewValue));
86 }); 105 });
87 } else { 106 } else {
88 valid = true; 107 valid = true;
89 } 108 }
90 } 109 }
91 110
92 /** 111 setValidity(String name, bool valid) {
93 * Sets the validity status of the given errorType on the model. Depending on if 112 this.updateControlValidity(this, name, valid);
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 }
117 } 113 }
118 114
119 /** 115 /**
120 * Registers a validator into the model to consider when running validate(). 116 * Registers a validator into the model to consider when running validate().
121 */ 117 */
122 addValidator(_NgModelValidator v) { 118 addValidator(NgValidatable v) {
123 validators.add(v); 119 validators.add(v);
124 validate(); 120 validate();
125 } 121 }
126 122
127 /** 123 /**
128 * De-registers a validator from the model. 124 * De-registers a validator from the model.
129 */ 125 */
130 removeValidator(_NgModelValidator v) { 126 removeValidator(NgValidatable v) {
131 validators.remove(v); 127 validators.remove(v);
132 validate(); 128 validate();
133 } 129 }
134
135 /**
136 * Removes the model from the control/form.
137 */
138 destroy() {
139 _form.removeControl(this);
140 }
141 } 130 }
142 131
143 /** 132 /**
144 * Usage: 133 * Usage:
145 * 134 *
146 * <input type="checkbox" ng-model="flag"> 135 * <input type="checkbox" ng-model="flag">
147 * 136 *
148 * This creates a two way databinding between the boolean expression specified i n 137 * This creates a two way databinding between the boolean expression specified
149 * ng-model and the checkbox input element in the DOM.  If the ng-model value is 138 * in ng-model and the checkbox input element in the DOM.  If the ng-model value
150 * falsy (i.e. one of `false`, `null`, and `0`), then the checkbox is unchecked. 139 * is falsy (i.e. one of `false`, `null`, and `0`), then the checkbox is
151 * Otherwise, it is checked.  Likewise, when the checkbox is checked, the model 140 * unchecked. Otherwise, it is checked.  Likewise, when the checkbox is checked,
152 * value is set to true. When unchecked, it is set to false. 141 * the model 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.
155 */ 142 */
156 @NgDirective(selector: 'input[type=checkbox][ng-model]') 143 @NgDirective(selector: 'input[type=checkbox][ng-model]')
157 class InputCheckboxDirective { 144 class InputCheckboxDirective {
158 dom.InputElement inputElement; 145 final dom.InputElement inputElement;
159 NgModel ngModel; 146 final NgModel ngModel;
160 Scope scope; 147 final NgTrueValue ngTrueValue;
148 final NgFalseValue ngFalseValue;
149 final Scope scope;
161 150
162 InputCheckboxDirective(dom.Element this.inputElement, this.ngModel, this.scope ) { 151 InputCheckboxDirective(dom.Element this.inputElement, this.ngModel,
152 this.scope, this.ngTrueValue, this.ngFalseValue) {
163 ngModel.render = (value) { 153 ngModel.render = (value) {
164 inputElement.checked = value == null ? false : toBool(value); 154 inputElement.checked = ngTrueValue.isValue(inputElement, value);
165 }; 155 };
166 inputElement.onChange.listen((value) { 156 inputElement.onChange.listen((value) {
167 scope.$apply(() => ngModel.viewValue = inputElement.checked); 157 ngModel.dirty = true;
158 ngModel.viewValue = inputElement.checked
159 ? ngTrueValue.readValue(inputElement)
160 : ngFalseValue.readValue(inputElement);
168 }); 161 });
169 } 162 }
170 } 163 }
171 164
172 /** 165 /**
173 * Usage: 166 * Usage:
174 * 167 *
175 * <input type="text|number|url|password|email" ng-model="myModel"> 168 * <input type="text|url|password|email" ng-model="myModel">
176 * <textarea ng-model="myModel"></textarea> 169 * <textarea ng-model="myModel"></textarea>
177 * 170 *
178 * This creates a two-way binding between any string-based input element 171 * This creates a two-way binding between any string-based input element
179 * (both <input> and <textarea>) so long as the ng-model attribute is 172 * (both <input> and <textarea>) so long as the ng-model attribute is
180 * present on the input element. Whenever the value of the input element 173 * present on the input element. Whenever the value of the input element
181 * changes then the matching model property on the scope will be updated 174 * changes then the matching model property on the scope will be updated
182 * as well as the other way around (when the scope property is updated). 175 * as well as the other way around (when the scope property is updated).
183 * 176 *
184 */ 177 */
185 @NgDirective(selector: 'textarea[ng-model]') 178 @NgDirective(selector: 'textarea[ng-model]')
186 @NgDirective(selector: 'input[type=text][ng-model]') 179 @NgDirective(selector: 'input[type=text][ng-model]')
187 @NgDirective(selector: 'input[type=password][ng-model]') 180 @NgDirective(selector: 'input[type=password][ng-model]')
188 @NgDirective(selector: 'input[type=url][ng-model]') 181 @NgDirective(selector: 'input[type=url][ng-model]')
189 @NgDirective(selector: 'input[type=email][ng-model]') 182 @NgDirective(selector: 'input[type=email][ng-model]')
190 @NgDirective(selector: 'input[type=number][ng-model]') 183 @NgDirective(selector: 'input[type=search][ng-model]')
191 class InputTextLikeDirective { 184 class InputTextLikeDirective {
192 dom.Element inputElement; 185 final dom.Element inputElement;
193 NgModel ngModel; 186 final NgModel ngModel;
194 Scope scope; 187 final Scope scope;
195 String _inputType; 188 String _inputType;
196 189
197 get typedValue => (inputElement as dynamic).value; 190 get typedValue => (inputElement as dynamic).value;
198 set typedValue(value) => (inputElement as dynamic).value = (value == null) ? ' ' : value.toString(); 191 set typedValue(value) => (inputElement as dynamic).value = (value == null) ?
192 '' :
193 value.toString();
199 194
200 InputTextLikeDirective(dom.Element this.inputElement, NgModel this.ngModel, Sc ope this.scope) { 195 InputTextLikeDirective(this.inputElement, this.ngModel, this.scope) {
201 ngModel.render = (value) { 196 ngModel.render = (value) {
202 if (value == null) value = ''; 197 if (value == null) value = '';
203 198
204 var currentValue = typedValue; 199 var currentValue = typedValue;
205 if (value != currentValue && !(value is num && currentValue is num && valu e.isNaN && currentValue.isNaN)) { 200 if (value != currentValue && !(value is num && currentValue is num &&
201 value.isNaN && currentValue.isNaN)) {
206 typedValue = value; 202 typedValue = value;
207 } 203 }
208 }; 204 };
209 inputElement.onChange.listen(relaxFnArgs(processValue)); 205 inputElement
210 inputElement.onKeyDown.listen((e) { 206 ..onChange.listen(processValue)
211 new async.Timer(Duration.ZERO, processValue); 207 ..onInput.listen(processValue)
212 scope.$skipAutoDigest(); 208 ..onBlur.listen((e) {
213 }); 209 if (ngModel.touched == null || ngModel.touched == false) {
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));
214 } 273 }
215 274
216 processValue() { 275 processValue() {
276 num value = typedValue;
277 if (value != ngModel.viewValue) {
278 ngModel.dirty = true;
279 scope.eval(() => ngModel.viewValue = value);
280 }
217 ngModel.validate(); 281 ngModel.validate();
218 var value = typedValue;
219 if (value != ngModel.viewValue) {
220 scope.$apply(() => ngModel.viewValue = value);
221 }
222 } 282 }
223 } 283 }
224 284
225 class _UidCounter { 285 class _UidCounter {
226 static final int CHAR_0 = "0".codeUnitAt(0); 286 static final int CHAR_0 = "0".codeUnitAt(0);
227 static final int CHAR_9 = "9".codeUnitAt(0); 287 static final int CHAR_9 = "9".codeUnitAt(0);
228 static final int CHAR_A = "A".codeUnitAt(0); 288 static final int CHAR_A = "A".codeUnitAt(0);
229 static final int CHAR_Z = "Z".codeUnitAt(0); 289 static final int CHAR_Z = "Z".codeUnitAt(0);
230 List charCodes = [CHAR_0, CHAR_0, CHAR_0]; 290 List charCodes = [CHAR_0, CHAR_0, CHAR_0];
231 291
232 String next() { 292 String next() {
233 for (int i = charCodes.length-1; i >= 0; i--) { 293 for (int i = charCodes.length - 1; i >= 0; i--) {
234 int code = charCodes[i]; 294 int code = charCodes[i];
235 if (code == CHAR_9) { 295 if (code == CHAR_9) {
236 charCodes[i] = CHAR_A; 296 charCodes[i] = CHAR_A;
237 return new String.fromCharCodes(charCodes); 297 return new String.fromCharCodes(charCodes);
238 } else if (code == CHAR_Z) { 298 } else if (code == CHAR_Z) {
239 charCodes[i] = CHAR_0; 299 charCodes[i] = CHAR_0;
240 } else { 300 } else {
241 charCodes[i] = code + 1; 301 charCodes[i] = code + 1;
242 return new String.fromCharCodes(charCodes); 302 return new String.fromCharCodes(charCodes);
243 } 303 }
244 } 304 }
245 charCodes.insert(0, CHAR_0); 305 charCodes.insert(0, CHAR_0);
246 return new String.fromCharCodes(charCodes); 306 return new String.fromCharCodes(charCodes);
247 } 307 }
248 } 308 }
249 309
250 final _uidCounter = new _UidCounter(); 310 final _uidCounter = new _UidCounter();
251 311
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 }
252 372
253 /** 373 /**
254 * Usage: 374 * Usage:
255 * 375 *
256 * <input type="radio" ng-model="category"> 376 * <input type="radio" ng-model="category">
257 * 377 *
258 * This creates a two way databinding between the expression specified in 378 * This creates a two way databinding between the expression specified in
259 * ng-model and the range input elements in the DOM.  If the ng-model value is 379 * ng-model and the range input elements in the DOM.  If the ng-model value is
260 * set to a value not corresponding to one of the radio elements, then none of 380 * set to a value not corresponding to one of the radio elements, then none of
261 * the radio elements will be check. Otherwise, only the corresponding input 381 * the radio elements will be check. Otherwise, only the corresponding input
262 * element in the group is checked. Likewise, when a radio button element is 382 * element in the group is checked. Likewise, when a radio button element is
263 * checked, the model is updated with its value. Radio buttons that have a 383 * checked, the model is updated with its value. Radio buttons that have a
264 * `name` attribute are left alone. Those that are missing the attribute will 384 * `name` attribute are left alone. Those that are missing the attribute will
265 * have a unique `name` assigned to them. This sequence goes `001`, `001`, ... 385 * have a unique `name` assigned to them. This sequence goes `001`, `001`, ...
266 * `009`, `00A`, `00Z`, `010`, … and so on using more than 3 characters for the 386 * `009`, `00A`, `00Z`, `010`, … and so on using more than 3 characters for the
267 * name when the counter overflows. 387 * name when the counter overflows.
268 */ 388 */
269 @NgDirective(selector: 'input[type=radio][ng-model]') 389 @NgDirective(selector: 'input[type=radio][ng-model]')
270 class InputRadioDirective { 390 class InputRadioDirective {
271 dom.RadioButtonInputElement radioButtonElement; 391 final dom.RadioButtonInputElement radioButtonElement;
272 NgModel ngModel; 392 final NgModel ngModel;
273 Scope scope; 393 final NgValue ngValue;
394 final Scope scope;
274 395
275 InputRadioDirective(dom.Element this.radioButtonElement, this.ngModel, 396 InputRadioDirective(dom.Element this.radioButtonElement, this.ngModel,
276 this.scope, NodeAttrs attrs) { 397 this.scope, this.ngValue, NodeAttrs attrs) {
277 // If there's no "name" set, we'll set a unique name. This ensures 398 // If there's no "name" set, we'll set a unique name. This ensures
278 // less surprising behavior about which radio buttons are grouped together. 399 // less surprising behavior about which radio buttons are grouped together.
279 if (attrs['name'] == '' || attrs['name'] == null) { 400 if (attrs['name'] == '' || attrs['name'] == null) {
280 attrs["name"] = _uidCounter.next(); 401 attrs["name"] = _uidCounter.next();
281 } 402 }
282 ngModel.render = (String value) { 403 ngModel.render = (value) {
283 radioButtonElement.checked = (value == radioButtonElement.value); 404 radioButtonElement.checked = (value == ngValue.readValue(radioButtonElemen t));
284 }; 405 };
285 radioButtonElement.onClick.listen((_) { 406 radioButtonElement.onClick.listen((_) {
286 if (radioButtonElement.checked) { 407 if (radioButtonElement.checked) {
287 scope.$apply(() => ngModel.viewValue = radioButtonElement.value); 408 ngModel.dirty = true;
409 ngModel.viewValue = ngValue.readValue(radioButtonElement);
288 } 410 }
289 }); 411 });
290 } 412 }
291 } 413 }
292 414
293 /** 415 /**
294 * Usage (span could be replaced with any element which supports text content, s uch as `p`): 416 * Usage (span could be replaced with any element which supports text content, s uch as `p`):
295 * 417 *
296 * <span contenteditable= ng-model="name"> 418 * <span contenteditable= ng-model="name">
297 * 419 *
298 * This creates a two way databinding between the expression specified in 420 * This creates a two way databinding between the expression specified in
299 * ng-model and the html element in the DOM.  If the ng-model value is 421 * ng-model and the html element in the DOM.  If the ng-model value is
300 * `null`, it is treated as equivalent to the empty string for rendering 422 * `null`, it is treated as equivalent to the empty string for rendering
301 * purposes. 423 * purposes.
302 */ 424 */
303 @NgDirective(selector: '[contenteditable][ng-model]') 425 @NgDirective(selector: '[contenteditable][ng-model]')
304 class ContentEditableDirective extends InputTextLikeDirective { 426 class ContentEditableDirective extends InputTextLikeDirective {
305 ContentEditableDirective(dom.Element inputElement, NgModel ngModel, Scope scop e): 427 ContentEditableDirective(dom.Element inputElement, NgModel ngModel,
306 super(inputElement, ngModel, scope); 428 Scope scope)
429 : super(inputElement, ngModel, scope);
307 430
308 // The implementation is identical to InputTextLikeDirective but use innerHtml instead of value 431 // The implementation is identical to InputTextLikeDirective but use innerHtml instead of value
309 get typedValue => (inputElement as dynamic).innerHtml; 432 get typedValue => (inputElement as dynamic).innerHtml;
310 set typedValue(String value) => (inputElement as dynamic).innerHtml = (value = = null) ? '' : value; 433 set typedValue(String value) =>
434 (inputElement as dynamic).innerHtml = (value == null) ? '' : value;
311 } 435 }
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