2015-02-12 14:44:59 +01:00
|
|
|
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';
|
2015-02-03 07:27:09 -08:00
|
|
|
import {ControlGroup, Control} from './model';
|
2015-02-11 11:10:31 -08:00
|
|
|
import * as validators from './validators';
|
2015-02-03 07:27:09 -08:00
|
|
|
|
2015-02-06 09:16:55 -08:00
|
|
|
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) {
|
2015-02-19 11:18:23 +01:00
|
|
|
return DOM.getValue(el);
|
2015-02-07 14:14:07 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
writeValue(el, value):void {
|
2015-02-19 11:18:23 +01:00
|
|
|
DOM.setValue(el,value);
|
2015-02-07 14:14:07 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@CONST()
|
|
|
|
class CheckboxControlValueAccessor extends ControlValueAccessor {
|
|
|
|
constructor() {
|
|
|
|
super();
|
|
|
|
}
|
|
|
|
|
|
|
|
readValue(el):boolean {
|
2015-02-19 11:18:23 +01:00
|
|
|
return DOM.getChecked(el);
|
2015-02-07 14:14:07 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
writeValue(el, value:boolean):void {
|
2015-02-19 11:18:23 +01:00
|
|
|
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");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-02-04 11:45:33 -08:00
|
|
|
export class ControlDirectiveBase {
|
|
|
|
_groupDecorator:ControlGroupDirectiveBase;
|
2015-02-03 07:27:09 -08:00
|
|
|
_el:NgElement;
|
2015-02-07 14:14:07 -08:00
|
|
|
|
|
|
|
controlName:string;
|
|
|
|
type:string;
|
|
|
|
valueAccessor:ControlValueAccessor;
|
2015-02-03 07:27:09 -08:00
|
|
|
|
2015-02-11 11:10:31 -08:00
|
|
|
validator:Function;
|
|
|
|
|
2015-02-04 11:45:33 -08:00
|
|
|
constructor(groupDecorator, el:NgElement) {
|
2015-02-03 07:27:09 -08:00
|
|
|
this._groupDecorator = groupDecorator;
|
|
|
|
this._el = el;
|
2015-02-11 11:10:31 -08:00
|
|
|
this.validator = validators.nullValidator;
|
2015-02-03 07:27:09 -08:00
|
|
|
}
|
|
|
|
|
2015-02-07 14:14:07 -08:00
|
|
|
_initialize() {
|
2015-02-11 11:10:31 -08:00
|
|
|
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-03 07:27:09 -08:00
|
|
|
}
|
|
|
|
|
2015-02-07 14:14:07 -08:00
|
|
|
_updateDomValue() {
|
|
|
|
this.valueAccessor.writeValue(this._el.domElement, this._control().value);
|
2015-02-04 11:45:33 -08:00
|
|
|
}
|
|
|
|
|
2015-02-07 14:14:07 -08:00
|
|
|
_updateControlValue() {
|
2015-02-11 11:10:31 -08:00
|
|
|
this._control().updateValue(this.valueAccessor.readValue(this._el.domElement));
|
2015-02-03 07:27:09 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
_control() {
|
2015-02-07 14:14:07 -08:00
|
|
|
return this._groupDecorator.findControl(this.controlName);
|
2015-02-03 07:27:09 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-02-04 11:45:33 -08:00
|
|
|
@Decorator({
|
2015-02-07 14:14:07 -08:00
|
|
|
lifecycle: [onChange],
|
2015-02-04 11:45:33 -08:00
|
|
|
selector: '[control-name]',
|
|
|
|
bind: {
|
2015-02-17 21:55:18 +01:00
|
|
|
'controlName' : 'control-name',
|
2015-02-07 14:14:07 -08:00
|
|
|
'type' : 'type'
|
2015-02-04 11:45:33 -08:00
|
|
|
}
|
|
|
|
})
|
|
|
|
export class ControlNameDirective extends ControlDirectiveBase {
|
|
|
|
constructor(@Ancestor() groupDecorator:ControlGroupDirective, el:NgElement) {
|
2015-02-06 09:16:55 -08:00
|
|
|
super(groupDecorator, el);
|
|
|
|
}
|
2015-02-07 14:14:07 -08:00
|
|
|
|
|
|
|
onChange(_) {
|
|
|
|
this._initialize();
|
|
|
|
}
|
2015-02-04 11:45:33 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
@Decorator({
|
2015-02-07 14:14:07 -08:00
|
|
|
lifecycle: [onChange],
|
2015-02-04 11:45:33 -08:00
|
|
|
selector: '[control]',
|
|
|
|
bind: {
|
2015-02-17 21:55:18 +01:00
|
|
|
'controlName' : 'control',
|
2015-02-07 14:14:07 -08:00
|
|
|
'type' : 'type'
|
2015-02-04 11:45:33 -08:00
|
|
|
}
|
|
|
|
})
|
|
|
|
export class ControlDirective extends ControlDirectiveBase {
|
|
|
|
constructor(@Ancestor() groupDecorator:NewControlGroupDirective, el:NgElement) {
|
2015-02-06 09:16:55 -08:00
|
|
|
super(groupDecorator, el);
|
|
|
|
}
|
2015-02-07 14:14:07 -08:00
|
|
|
|
|
|
|
onChange(_) {
|
|
|
|
this._initialize();
|
|
|
|
}
|
2015-02-04 11:45:33 -08:00
|
|
|
}
|
|
|
|
|
2015-02-03 07:27:09 -08:00
|
|
|
@Decorator({
|
|
|
|
selector: '[control-group]',
|
|
|
|
bind: {
|
2015-02-17 21:55:18 +01:00
|
|
|
'controlGroup' : 'control-group'
|
2015-02-03 07:27:09 -08:00
|
|
|
}
|
|
|
|
})
|
2015-02-04 11:45:33 -08:00
|
|
|
export class ControlGroupDirective extends ControlGroupDirectiveBase {
|
2015-02-03 07:27:09 -08:00
|
|
|
_controlGroup:ControlGroup;
|
2015-02-04 11:45:33 -08:00
|
|
|
_directives:List<ControlNameDirective>;
|
2015-02-03 07:27:09 -08:00
|
|
|
|
|
|
|
constructor() {
|
2015-02-06 13:38:52 -08:00
|
|
|
super();
|
2015-02-04 11:45:33 -08:00
|
|
|
this._directives = ListWrapper.create();
|
2015-02-03 07:27:09 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
set controlGroup(controlGroup:ControlGroup) {
|
|
|
|
this._controlGroup = controlGroup;
|
2015-02-07 14:14:07 -08:00
|
|
|
ListWrapper.forEach(this._directives, (cd) => cd._updateDomValue());
|
2015-02-03 07:27:09 -08:00
|
|
|
}
|
|
|
|
|
2015-02-04 11:45:33 -08:00
|
|
|
addDirective(c:ControlNameDirective) {
|
|
|
|
ListWrapper.push(this._directives, c);
|
2015-02-03 07:27:09 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
findControl(name:string):Control {
|
|
|
|
return this._controlGroup.controls[name];
|
|
|
|
}
|
|
|
|
}
|
2015-02-04 11:45:33 -08:00
|
|
|
|
|
|
|
@Component({
|
|
|
|
selector: '[new-control-group]',
|
|
|
|
bind: {
|
2015-02-17 21:55:18 +01:00
|
|
|
'initData' : 'new-control-group'
|
2015-02-12 14:44:59 +01:00
|
|
|
}
|
2015-02-04 11:45:33 -08:00
|
|
|
})
|
2015-02-12 14:44:59 +01:00
|
|
|
@Template({inline: '<content>'})
|
2015-02-04 11:45:33 -08:00
|
|
|
export class NewControlGroupDirective extends ControlGroupDirectiveBase {
|
|
|
|
_initData:any;
|
|
|
|
_controlGroup:ControlGroup;
|
|
|
|
_directives:List<ControlNameDirective>;
|
|
|
|
|
|
|
|
constructor() {
|
2015-02-06 13:38:52 -08:00
|
|
|
super();
|
2015-02-04 11:45:33 -08:00
|
|
|
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);
|
2015-02-04 11:45:33 -08:00
|
|
|
return memo;
|
|
|
|
}, {});
|
|
|
|
return new ControlGroup(controls);
|
|
|
|
}
|
|
|
|
|
|
|
|
get value() {
|
|
|
|
return this._controlGroup.value;
|
|
|
|
}
|
2015-02-11 11:10:31 -08:00
|
|
|
|
|
|
|
get errors() {
|
|
|
|
return this._controlGroup.errors;
|
|
|
|
}
|
|
|
|
|
|
|
|
get valid() {
|
|
|
|
return this._controlGroup.valid;
|
|
|
|
}
|
2015-02-04 11:45:33 -08:00
|
|
|
}
|
2015-02-07 14:14:07 -08:00
|
|
|
|
|
|
|
export var FormDirectives = [
|
|
|
|
ControlGroupDirective, ControlNameDirective,
|
|
|
|
ControlDirective, NewControlGroupDirective
|
|
|
|
];
|