Skip to content

Commit 514529b

Browse files
committed
refactor(formed): changed forms to use event and property setters instead of NgElement
1 parent a12dc7d commit 514529b

File tree

3 files changed

+85
-66
lines changed

3 files changed

+85
-66
lines changed

modules/angular2/core.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ export * from './src/core/annotations/visibility';
22
export * from './src/core/compiler/interfaces';
33
export * from './src/core/annotations/template';
44
export * from './src/core/application';
5+
export * from './src/core/annotations/di';
56

67
export * from './src/core/compiler/compiler';
78

modules/angular2/src/forms/directives.js

Lines changed: 43 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -1,84 +1,77 @@
1-
import {Template, Component, Decorator, NgElement, Ancestor, onChange} from 'angular2/angular2';
1+
import {Template, Component, Decorator, Ancestor, onChange, PropertySetter} from 'angular2/angular2';
22
import {Optional} from 'angular2/di';
33
import {DOM} from 'angular2/src/dom/dom_adapter';
44
import {isBlank, isPresent, isString, CONST} from 'angular2/src/facade/lang';
55
import {StringMapWrapper, ListWrapper} from 'angular2/src/facade/collection';
66
import {ControlGroup, Control} from './model';
77
import {Validators} from './validators';
88

9-
@CONST()
109
export class ControlValueAccessor {
11-
readValue(el){}
12-
writeValue(el, value):void {}
10+
writeValue(value):void{}
11+
set onChange(fn){}
1312
}
1413

15-
@CONST()
16-
class DefaultControlValueAccessor extends ControlValueAccessor {
17-
constructor() {
18-
super();
14+
@Decorator({
15+
selector: '[control]',
16+
events: {
17+
'change' : 'onChange($event.target.value)'
1918
}
19+
})
20+
export class DefaultControlDecorator extends ControlValueAccessor {
21+
_setValueProperty:Function;
22+
onChange:Function;
2023

21-
readValue(el) {
22-
return DOM.getValue(el);
24+
constructor(@PropertySetter('value') setValueProperty:Function) {
25+
this._setValueProperty = setValueProperty;
26+
this.onChange = (_) => {};
2327
}
2428

25-
writeValue(el, value):void {
26-
DOM.setValue(el,value);
29+
writeValue(value) {
30+
this._setValueProperty(value);
2731
}
2832
}
2933

30-
@CONST()
31-
class CheckboxControlValueAccessor extends ControlValueAccessor {
32-
constructor() {
33-
super();
34-
}
35-
36-
readValue(el):boolean {
37-
return DOM.getChecked(el);
34+
@Decorator({
35+
selector: 'input[type=checkbox]', //should be input[type=checkbox][control]
36+
events: {
37+
'change' : 'onChange($event.target.checked)'
3838
}
39+
})
40+
export class CheckboxControlDecorator extends ControlValueAccessor {
41+
_setCheckedProperty:Function;
42+
onChange:Function;
3943

40-
writeValue(el, value:boolean):void {
41-
DOM.setChecked(el, value);
44+
constructor(cd:ControlDirective, @PropertySetter('checked') setCheckedProperty:Function) {
45+
this._setCheckedProperty = setCheckedProperty;
46+
this.onChange = (_) => {};
47+
//TODO: vsavkin ControlDirective should inject CheckboxControlDirective
48+
cd.valueAccessor = this;
4249
}
43-
}
4450

45-
var controlValueAccessors = {
46-
"checkbox" : new CheckboxControlValueAccessor(),
47-
"text" : new DefaultControlValueAccessor()
48-
};
49-
50-
function controlValueAccessorFor(controlType:string):ControlValueAccessor {
51-
var accessor = StringMapWrapper.get(controlValueAccessors, controlType);
52-
if (isPresent(accessor)) {
53-
return accessor;
54-
} else {
55-
return StringMapWrapper.get(controlValueAccessors, "text");
51+
writeValue(value) {
52+
this._setCheckedProperty(value);
5653
}
5754
}
5855

5956
@Decorator({
6057
lifecycle: [onChange],
6158
selector: '[control]',
6259
bind: {
63-
'controlName' : 'control',
64-
'type' : 'type'
60+
'controlName' : 'control'
6561
}
6662
})
6763
export class ControlDirective {
6864
_groupDirective:ControlGroupDirective;
69-
_el:NgElement;
7065

7166
controlName:string;
72-
type:string;
7367
valueAccessor:ControlValueAccessor;
7468

7569
validator:Function;
7670

77-
constructor(@Ancestor() groupDirective:ControlGroupDirective, el:NgElement) {
71+
constructor(@Ancestor() groupDirective:ControlGroupDirective, valueAccessor:DefaultControlDecorator) {
7872
this._groupDirective = groupDirective;
79-
this._el = el;
8073
this.controlName = null;
81-
this.type = null;
74+
this.valueAccessor = valueAccessor;
8275
this.validator = Validators.nullValidator;
8376
}
8477

@@ -94,20 +87,20 @@ export class ControlDirective {
9487
var c = this._control();
9588
c.validator = Validators.compose([c.validator, this.validator]);
9689

97-
if (isBlank(this.valueAccessor)) {
98-
this.valueAccessor = controlValueAccessorFor(this.type);
99-
}
100-
10190
this._updateDomValue();
102-
DOM.on(this._el.domElement, "change", (_) => this._updateControlValue());
91+
this._setUpUpdateControlValue();
10392
}
10493

10594
_updateDomValue() {
106-
this.valueAccessor.writeValue(this._el.domElement, this._control().value);
95+
this.valueAccessor.writeValue(this._control().value);
96+
}
97+
98+
_setUpUpdateControlValue() {
99+
this.valueAccessor.onChange = (newValue) => this._control().updateValue(newValue);
107100
}
108101

109-
_updateControlValue() {
110-
this._control().updateValue(this.valueAccessor.readValue(this._el.domElement));
102+
_updateControlValue(newValue) {
103+
this._control().updateValue(newValue);
111104
}
112105

113106
_control() {
@@ -165,5 +158,5 @@ export class ControlGroupDirective {
165158
}
166159

167160
export var FormDirectives = [
168-
ControlGroupDirective, ControlDirective
161+
ControlGroupDirective, ControlDirective, CheckboxControlDecorator, DefaultControlDecorator
169162
];

modules/angular2/test/forms/integration_spec.js

Lines changed: 41 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -24,14 +24,17 @@ import {ComponentUrlMapper} from 'angular2/src/core/compiler/component_url_mappe
2424
import {UrlResolver} from 'angular2/src/core/compiler/url_resolver';
2525
import {StyleUrlResolver} from 'angular2/src/core/compiler/style_url_resolver';
2626
import {CssProcessor} from 'angular2/src/core/compiler/css_processor';
27+
import {EventManager, DomEventsPlugin} from 'angular2/src/core/events/event_manager';
28+
import {VmTurnZone} from 'angular2/src/core/zone/vm_turn_zone';
2729

2830
import {MockTemplateResolver} from 'angular2/src/mock/template_resolver_mock';
2931

3032
import {Injector} from 'angular2/di';
3133

32-
import {Component, Decorator, Template} from 'angular2/angular2';
34+
import {Component, Decorator, Template, PropertySetter} from 'angular2/angular2';
3335
import {ControlGroupDirective, ControlDirective, Control, ControlGroup, OptionalControl,
34-
ControlValueAccessor, RequiredValidatorDirective, Validators} from 'angular2/forms';
36+
ControlValueAccessor, RequiredValidatorDirective, CheckboxControlDecorator,
37+
DefaultControlDecorator, Validators} from 'angular2/forms';
3538

3639
export function main() {
3740
function detectChanges(view) {
@@ -56,11 +59,13 @@ export function main() {
5659

5760
tplResolver.setTemplate(componentType, new Template({
5861
inline: template,
59-
directives: [ControlGroupDirective, ControlDirective, WrappedValue, RequiredValidatorDirective]
62+
directives: [ControlGroupDirective, ControlDirective, WrappedValue, RequiredValidatorDirective,
63+
CheckboxControlDecorator, DefaultControlDecorator]
6064
}));
6165

6266
compiler.compile(componentType).then((pv) => {
63-
var view = pv.instantiate(null, null);
67+
var eventManager = new EventManager([new DomEventsPlugin()], new FakeVmTurnZone());
68+
var view = pv.instantiate(null, eventManager);
6469
view.hydrate(new Injector([]), null, null, context, null);
6570
detectChanges(view);
6671
callback(view);
@@ -346,21 +351,41 @@ class MyComp {
346351
}
347352
}
348353

349-
class WrappedValueAccessor extends ControlValueAccessor {
350-
readValue(el){
351-
return el.value.substring(1, el.value.length - 1);
354+
355+
@Decorator({
356+
selector:'[wrapped-value]',
357+
events: {
358+
'change' : 'handleOnChange($event.target.value)'
352359
}
360+
})
361+
class WrappedValue extends ControlValueAccessor {
362+
_setProperty:Function;
363+
onChange:Function;
353364

354-
writeValue(el, value):void {
355-
el.value = `!${value}!`;
365+
constructor(cd:ControlDirective, @PropertySetter('value') setProperty:Function) {
366+
this._setProperty = setProperty;
367+
cd.valueAccessor = this;
356368
}
357-
}
358369

359-
@Decorator({
360-
selector:'[wrapped-value]'
361-
})
362-
class WrappedValue {
363-
constructor(cd:ControlDirective) {
364-
cd.valueAccessor = new WrappedValueAccessor();
370+
writeValue(value) {
371+
this._setProperty(`!${value}!`);
372+
}
373+
374+
handleOnChange(value) {
375+
this.onChange(value.substring(1, value.length - 1));
365376
}
366377
}
378+
379+
class FakeVmTurnZone extends VmTurnZone {
380+
constructor() {
381+
super({enableLongStackTrace: false});
382+
}
383+
384+
run(fn) {
385+
fn();
386+
}
387+
388+
runOutsideAngular(fn) {
389+
fn();
390+
}
391+
}

0 commit comments

Comments
 (0)