232 lines
5.2 KiB
JavaScript
Raw Normal View History

import {Template, Component, Decorator, NgElement, Ancestor, onChange} from 'angular2/core';
2015-02-05 14:09:26 -08:00
import {DOM} from 'angular2/src/facade/dom';
2015-02-07 14:14:07 -08:00
import {isBlank, isPresent, CONST} from 'angular2/src/facade/lang';
import {StringMapWrapper, ListWrapper} from 'angular2/src/facade/collection';
import {ControlGroup, Control} from './model';
import * as validators from './validators';
class ControlGroupDirectiveBase {
addDirective(directive):void {}
findControl(name:string):Control { return null; }
}
2015-02-07 14:14:07 -08:00
@CONST()
export class ControlValueAccessor {
readValue(el){}
writeValue(el, value):void {}
}
@CONST()
class DefaultControlValueAccessor extends ControlValueAccessor {
constructor() {
super();
}
readValue(el) {
return DOM.getValue(el);
2015-02-07 14:14:07 -08:00
}
writeValue(el, value):void {
DOM.setValue(el,value);
2015-02-07 14:14:07 -08:00
}
}
@CONST()
class CheckboxControlValueAccessor extends ControlValueAccessor {
constructor() {
super();
}
readValue(el):boolean {
return DOM.getChecked(el);
2015-02-07 14:14:07 -08:00
}
writeValue(el, value:boolean):void {
DOM.setChecked(el, value);
2015-02-07 14:14:07 -08:00
}
}
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");
}
}
export class ControlDirectiveBase {
_groupDecorator:ControlGroupDirectiveBase;
_el:NgElement;
2015-02-07 14:14:07 -08:00
controlName:string;
type:string;
valueAccessor:ControlValueAccessor;
validator:Function;
constructor(groupDecorator, el:NgElement) {
this._groupDecorator = groupDecorator;
this._el = el;
this.validator = validators.nullValidator;
}
2015-02-07 14:14:07 -08:00
_initialize() {
this._groupDecorator.addDirective(this);
if (isPresent(this.validator)) {
var c = this._control();
c.validator = validators.compose([c.validator, this.validator]);
}
2015-02-07 14:14:07 -08:00
if (isBlank(this.valueAccessor)) {
this.valueAccessor = controlValueAccessorFor(this.type);
}
this._updateDomValue();
DOM.on(this._el.domElement, "change", (_) => this._updateControlValue());
}
2015-02-07 14:14:07 -08:00
_updateDomValue() {
this.valueAccessor.writeValue(this._el.domElement, this._control().value);
}
2015-02-07 14:14:07 -08:00
_updateControlValue() {
this._control().updateValue(this.valueAccessor.readValue(this._el.domElement));
}
_control() {
2015-02-07 14:14:07 -08:00
return this._groupDecorator.findControl(this.controlName);
}
}
@Decorator({
2015-02-07 14:14:07 -08:00
lifecycle: [onChange],
selector: '[control-name]',
bind: {
'controlName' : 'control-name',
2015-02-07 14:14:07 -08:00
'type' : 'type'
}
})
export class ControlNameDirective extends ControlDirectiveBase {
constructor(@Ancestor() groupDecorator:ControlGroupDirective, el:NgElement) {
super(groupDecorator, el);
}
2015-02-07 14:14:07 -08:00
onChange(_) {
this._initialize();
}
}
@Decorator({
2015-02-07 14:14:07 -08:00
lifecycle: [onChange],
selector: '[control]',
bind: {
'controlName' : 'control',
2015-02-07 14:14:07 -08:00
'type' : 'type'
}
})
export class ControlDirective extends ControlDirectiveBase {
constructor(@Ancestor() groupDecorator:NewControlGroupDirective, el:NgElement) {
super(groupDecorator, el);
}
2015-02-07 14:14:07 -08:00
onChange(_) {
this._initialize();
}
}
@Decorator({
selector: '[control-group]',
bind: {
'controlGroup' : 'control-group'
}
})
export class ControlGroupDirective extends ControlGroupDirectiveBase {
_controlGroup:ControlGroup;
_directives:List<ControlNameDirective>;
constructor() {
super();
this._directives = ListWrapper.create();
}
set controlGroup(controlGroup:ControlGroup) {
this._controlGroup = controlGroup;
2015-02-07 14:14:07 -08:00
ListWrapper.forEach(this._directives, (cd) => cd._updateDomValue());
}
addDirective(c:ControlNameDirective) {
ListWrapper.push(this._directives, c);
}
findControl(name:string):Control {
return this._controlGroup.controls[name];
}
}
@Component({
selector: '[new-control-group]',
bind: {
'initData' : 'new-control-group'
}
})
@Template({inline: '<content>'})
export class NewControlGroupDirective extends ControlGroupDirectiveBase {
_initData:any;
_controlGroup:ControlGroup;
_directives:List<ControlNameDirective>;
constructor() {
super();
this._directives = ListWrapper.create();
}
set initData(value) {
this._initData = value;
}
addDirective(c:ControlDirective) {
ListWrapper.push(this._directives, c);
this._controlGroup = null;
}
findControl(name:string):Control {
if (isBlank(this._controlGroup)) {
this._controlGroup = this._createControlGroup();
}
return this._controlGroup.controls[name];
}
_createControlGroup():ControlGroup {
var controls = ListWrapper.reduce(this._directives, (memo, cd) => {
2015-02-07 14:14:07 -08:00
var initControlValue = this._initData[cd.controlName];
memo[cd.controlName] = new Control(initControlValue);
return memo;
}, {});
return new ControlGroup(controls);
}
get value() {
return this._controlGroup.value;
}
get errors() {
return this._controlGroup.errors;
}
get valid() {
return this._controlGroup.valid;
}
}
2015-02-07 14:14:07 -08:00
export var FormDirectives = [
ControlGroupDirective, ControlNameDirective,
ControlDirective, NewControlGroupDirective
];