refactor(formed): changed forms to use event and property setters instead of NgElement
This commit is contained in:
parent
a12dc7d75a
commit
514529b5d9
|
@ -2,6 +2,7 @@ export * from './src/core/annotations/visibility';
|
||||||
export * from './src/core/compiler/interfaces';
|
export * from './src/core/compiler/interfaces';
|
||||||
export * from './src/core/annotations/template';
|
export * from './src/core/annotations/template';
|
||||||
export * from './src/core/application';
|
export * from './src/core/application';
|
||||||
|
export * from './src/core/annotations/di';
|
||||||
|
|
||||||
export * from './src/core/compiler/compiler';
|
export * from './src/core/compiler/compiler';
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import {Template, Component, Decorator, NgElement, Ancestor, onChange} from 'angular2/angular2';
|
import {Template, Component, Decorator, Ancestor, onChange, PropertySetter} from 'angular2/angular2';
|
||||||
import {Optional} from 'angular2/di';
|
import {Optional} from 'angular2/di';
|
||||||
import {DOM} from 'angular2/src/dom/dom_adapter';
|
import {DOM} from 'angular2/src/dom/dom_adapter';
|
||||||
import {isBlank, isPresent, isString, CONST} from 'angular2/src/facade/lang';
|
import {isBlank, isPresent, isString, CONST} from 'angular2/src/facade/lang';
|
||||||
|
@ -6,53 +6,50 @@ import {StringMapWrapper, ListWrapper} from 'angular2/src/facade/collection';
|
||||||
import {ControlGroup, Control} from './model';
|
import {ControlGroup, Control} from './model';
|
||||||
import {Validators} from './validators';
|
import {Validators} from './validators';
|
||||||
|
|
||||||
@CONST()
|
|
||||||
export class ControlValueAccessor {
|
export class ControlValueAccessor {
|
||||||
readValue(el){}
|
writeValue(value):void{}
|
||||||
writeValue(el, value):void {}
|
set onChange(fn){}
|
||||||
}
|
}
|
||||||
|
|
||||||
@CONST()
|
@Decorator({
|
||||||
class DefaultControlValueAccessor extends ControlValueAccessor {
|
selector: '[control]',
|
||||||
constructor() {
|
events: {
|
||||||
super();
|
'change' : 'onChange($event.target.value)'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
export class DefaultControlDecorator extends ControlValueAccessor {
|
||||||
|
_setValueProperty:Function;
|
||||||
|
onChange:Function;
|
||||||
|
|
||||||
|
constructor(@PropertySetter('value') setValueProperty:Function) {
|
||||||
|
this._setValueProperty = setValueProperty;
|
||||||
|
this.onChange = (_) => {};
|
||||||
}
|
}
|
||||||
|
|
||||||
readValue(el) {
|
writeValue(value) {
|
||||||
return DOM.getValue(el);
|
this._setValueProperty(value);
|
||||||
}
|
|
||||||
|
|
||||||
writeValue(el, value):void {
|
|
||||||
DOM.setValue(el,value);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@CONST()
|
@Decorator({
|
||||||
class CheckboxControlValueAccessor extends ControlValueAccessor {
|
selector: 'input[type=checkbox]', //should be input[type=checkbox][control]
|
||||||
constructor() {
|
events: {
|
||||||
super();
|
'change' : 'onChange($event.target.checked)'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
export class CheckboxControlDecorator extends ControlValueAccessor {
|
||||||
|
_setCheckedProperty:Function;
|
||||||
|
onChange:Function;
|
||||||
|
|
||||||
|
constructor(cd:ControlDirective, @PropertySetter('checked') setCheckedProperty:Function) {
|
||||||
|
this._setCheckedProperty = setCheckedProperty;
|
||||||
|
this.onChange = (_) => {};
|
||||||
|
//TODO: vsavkin ControlDirective should inject CheckboxControlDirective
|
||||||
|
cd.valueAccessor = this;
|
||||||
}
|
}
|
||||||
|
|
||||||
readValue(el):boolean {
|
writeValue(value) {
|
||||||
return DOM.getChecked(el);
|
this._setCheckedProperty(value);
|
||||||
}
|
|
||||||
|
|
||||||
writeValue(el, value:boolean):void {
|
|
||||||
DOM.setChecked(el, value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var controlValueAccessors = {
|
|
||||||
"checkbox" : new CheckboxControlValueAccessor(),
|
|
||||||
"text" : new DefaultControlValueAccessor()
|
|
||||||
};
|
|
||||||
|
|
||||||
function controlValueAccessorFor(controlType:string):ControlValueAccessor {
|
|
||||||
var accessor = StringMapWrapper.get(controlValueAccessors, controlType);
|
|
||||||
if (isPresent(accessor)) {
|
|
||||||
return accessor;
|
|
||||||
} else {
|
|
||||||
return StringMapWrapper.get(controlValueAccessors, "text");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -60,25 +57,21 @@ function controlValueAccessorFor(controlType:string):ControlValueAccessor {
|
||||||
lifecycle: [onChange],
|
lifecycle: [onChange],
|
||||||
selector: '[control]',
|
selector: '[control]',
|
||||||
bind: {
|
bind: {
|
||||||
'controlName' : 'control',
|
'controlName' : 'control'
|
||||||
'type' : 'type'
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
export class ControlDirective {
|
export class ControlDirective {
|
||||||
_groupDirective:ControlGroupDirective;
|
_groupDirective:ControlGroupDirective;
|
||||||
_el:NgElement;
|
|
||||||
|
|
||||||
controlName:string;
|
controlName:string;
|
||||||
type:string;
|
|
||||||
valueAccessor:ControlValueAccessor;
|
valueAccessor:ControlValueAccessor;
|
||||||
|
|
||||||
validator:Function;
|
validator:Function;
|
||||||
|
|
||||||
constructor(@Ancestor() groupDirective:ControlGroupDirective, el:NgElement) {
|
constructor(@Ancestor() groupDirective:ControlGroupDirective, valueAccessor:DefaultControlDecorator) {
|
||||||
this._groupDirective = groupDirective;
|
this._groupDirective = groupDirective;
|
||||||
this._el = el;
|
|
||||||
this.controlName = null;
|
this.controlName = null;
|
||||||
this.type = null;
|
this.valueAccessor = valueAccessor;
|
||||||
this.validator = Validators.nullValidator;
|
this.validator = Validators.nullValidator;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -94,20 +87,20 @@ export class ControlDirective {
|
||||||
var c = this._control();
|
var c = this._control();
|
||||||
c.validator = Validators.compose([c.validator, this.validator]);
|
c.validator = Validators.compose([c.validator, this.validator]);
|
||||||
|
|
||||||
if (isBlank(this.valueAccessor)) {
|
|
||||||
this.valueAccessor = controlValueAccessorFor(this.type);
|
|
||||||
}
|
|
||||||
|
|
||||||
this._updateDomValue();
|
this._updateDomValue();
|
||||||
DOM.on(this._el.domElement, "change", (_) => this._updateControlValue());
|
this._setUpUpdateControlValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
_updateDomValue() {
|
_updateDomValue() {
|
||||||
this.valueAccessor.writeValue(this._el.domElement, this._control().value);
|
this.valueAccessor.writeValue(this._control().value);
|
||||||
}
|
}
|
||||||
|
|
||||||
_updateControlValue() {
|
_setUpUpdateControlValue() {
|
||||||
this._control().updateValue(this.valueAccessor.readValue(this._el.domElement));
|
this.valueAccessor.onChange = (newValue) => this._control().updateValue(newValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
_updateControlValue(newValue) {
|
||||||
|
this._control().updateValue(newValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
_control() {
|
_control() {
|
||||||
|
@ -165,5 +158,5 @@ export class ControlGroupDirective {
|
||||||
}
|
}
|
||||||
|
|
||||||
export var FormDirectives = [
|
export var FormDirectives = [
|
||||||
ControlGroupDirective, ControlDirective
|
ControlGroupDirective, ControlDirective, CheckboxControlDecorator, DefaultControlDecorator
|
||||||
];
|
];
|
||||||
|
|
|
@ -24,14 +24,17 @@ import {ComponentUrlMapper} from 'angular2/src/core/compiler/component_url_mappe
|
||||||
import {UrlResolver} from 'angular2/src/core/compiler/url_resolver';
|
import {UrlResolver} from 'angular2/src/core/compiler/url_resolver';
|
||||||
import {StyleUrlResolver} from 'angular2/src/core/compiler/style_url_resolver';
|
import {StyleUrlResolver} from 'angular2/src/core/compiler/style_url_resolver';
|
||||||
import {CssProcessor} from 'angular2/src/core/compiler/css_processor';
|
import {CssProcessor} from 'angular2/src/core/compiler/css_processor';
|
||||||
|
import {EventManager, DomEventsPlugin} from 'angular2/src/core/events/event_manager';
|
||||||
|
import {VmTurnZone} from 'angular2/src/core/zone/vm_turn_zone';
|
||||||
|
|
||||||
import {MockTemplateResolver} from 'angular2/src/mock/template_resolver_mock';
|
import {MockTemplateResolver} from 'angular2/src/mock/template_resolver_mock';
|
||||||
|
|
||||||
import {Injector} from 'angular2/di';
|
import {Injector} from 'angular2/di';
|
||||||
|
|
||||||
import {Component, Decorator, Template} from 'angular2/angular2';
|
import {Component, Decorator, Template, PropertySetter} from 'angular2/angular2';
|
||||||
import {ControlGroupDirective, ControlDirective, Control, ControlGroup, OptionalControl,
|
import {ControlGroupDirective, ControlDirective, Control, ControlGroup, OptionalControl,
|
||||||
ControlValueAccessor, RequiredValidatorDirective, Validators} from 'angular2/forms';
|
ControlValueAccessor, RequiredValidatorDirective, CheckboxControlDecorator,
|
||||||
|
DefaultControlDecorator, Validators} from 'angular2/forms';
|
||||||
|
|
||||||
export function main() {
|
export function main() {
|
||||||
function detectChanges(view) {
|
function detectChanges(view) {
|
||||||
|
@ -56,11 +59,13 @@ export function main() {
|
||||||
|
|
||||||
tplResolver.setTemplate(componentType, new Template({
|
tplResolver.setTemplate(componentType, new Template({
|
||||||
inline: template,
|
inline: template,
|
||||||
directives: [ControlGroupDirective, ControlDirective, WrappedValue, RequiredValidatorDirective]
|
directives: [ControlGroupDirective, ControlDirective, WrappedValue, RequiredValidatorDirective,
|
||||||
|
CheckboxControlDecorator, DefaultControlDecorator]
|
||||||
}));
|
}));
|
||||||
|
|
||||||
compiler.compile(componentType).then((pv) => {
|
compiler.compile(componentType).then((pv) => {
|
||||||
var view = pv.instantiate(null, null);
|
var eventManager = new EventManager([new DomEventsPlugin()], new FakeVmTurnZone());
|
||||||
|
var view = pv.instantiate(null, eventManager);
|
||||||
view.hydrate(new Injector([]), null, null, context, null);
|
view.hydrate(new Injector([]), null, null, context, null);
|
||||||
detectChanges(view);
|
detectChanges(view);
|
||||||
callback(view);
|
callback(view);
|
||||||
|
@ -346,21 +351,41 @@ class MyComp {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class WrappedValueAccessor extends ControlValueAccessor {
|
|
||||||
readValue(el){
|
|
||||||
return el.value.substring(1, el.value.length - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
writeValue(el, value):void {
|
|
||||||
el.value = `!${value}!`;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Decorator({
|
@Decorator({
|
||||||
selector:'[wrapped-value]'
|
selector:'[wrapped-value]',
|
||||||
|
events: {
|
||||||
|
'change' : 'handleOnChange($event.target.value)'
|
||||||
|
}
|
||||||
})
|
})
|
||||||
class WrappedValue {
|
class WrappedValue extends ControlValueAccessor {
|
||||||
constructor(cd:ControlDirective) {
|
_setProperty:Function;
|
||||||
cd.valueAccessor = new WrappedValueAccessor();
|
onChange:Function;
|
||||||
|
|
||||||
|
constructor(cd:ControlDirective, @PropertySetter('value') setProperty:Function) {
|
||||||
|
this._setProperty = setProperty;
|
||||||
|
cd.valueAccessor = this;
|
||||||
|
}
|
||||||
|
|
||||||
|
writeValue(value) {
|
||||||
|
this._setProperty(`!${value}!`);
|
||||||
|
}
|
||||||
|
|
||||||
|
handleOnChange(value) {
|
||||||
|
this.onChange(value.substring(1, value.length - 1));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class FakeVmTurnZone extends VmTurnZone {
|
||||||
|
constructor() {
|
||||||
|
super({enableLongStackTrace: false});
|
||||||
|
}
|
||||||
|
|
||||||
|
run(fn) {
|
||||||
|
fn();
|
||||||
|
}
|
||||||
|
|
||||||
|
runOutsideAngular(fn) {
|
||||||
|
fn();
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue