2015-02-11 11:10:31 -08:00
|
|
|
import {isPresent} from 'angular2/src/facade/lang';
|
2015-03-24 13:45:47 -07:00
|
|
|
import {Observable, ObservableWrapper} from 'angular2/src/facade/async';
|
2015-03-25 10:51:05 -07:00
|
|
|
import {StringMap, StringMapWrapper, ListWrapper, List} from 'angular2/src/facade/collection';
|
2015-03-19 14:21:40 -07:00
|
|
|
import {Validators} from './validators';
|
2015-02-11 11:10:31 -08:00
|
|
|
|
|
|
|
export const VALID = "VALID";
|
|
|
|
export const INVALID = "INVALID";
|
2015-02-03 07:27:09 -08:00
|
|
|
|
2015-02-24 11:59:10 -08:00
|
|
|
//interface IControl {
|
|
|
|
// get value():any;
|
|
|
|
// validator:Function;
|
|
|
|
// get status():string;
|
2015-02-25 12:54:27 -08:00
|
|
|
// get valid():boolean;
|
2015-02-24 11:59:10 -08:00
|
|
|
// get errors():Map;
|
2015-03-19 10:51:49 -07:00
|
|
|
// get pristine():boolean;
|
|
|
|
// get dirty():boolean;
|
2015-02-24 11:59:10 -08:00
|
|
|
// updateValue(value:any){}
|
|
|
|
// setParent(parent){}
|
|
|
|
//}
|
|
|
|
|
2015-02-25 15:10:27 -08:00
|
|
|
export class AbstractControl {
|
2015-02-24 11:59:10 -08:00
|
|
|
_value:any;
|
|
|
|
_status:string;
|
|
|
|
_errors;
|
2015-03-19 10:51:49 -07:00
|
|
|
_pristine:boolean;
|
2015-03-25 10:51:05 -07:00
|
|
|
_parent:any; /* ControlGroup | ControlArray */
|
2015-02-24 11:59:10 -08:00
|
|
|
validator:Function;
|
2015-02-03 07:27:09 -08:00
|
|
|
|
2015-03-25 10:51:05 -07:00
|
|
|
valueChanges:Observable;
|
|
|
|
_valueChangesController;
|
|
|
|
|
2015-03-19 14:21:40 -07:00
|
|
|
constructor(validator:Function) {
|
2015-02-11 11:10:31 -08:00
|
|
|
this.validator = validator;
|
2015-03-19 10:51:49 -07:00
|
|
|
this._pristine = true;
|
2015-02-11 11:10:31 -08:00
|
|
|
}
|
|
|
|
|
2015-02-24 11:59:10 -08:00
|
|
|
get value() {
|
|
|
|
return this._value;
|
|
|
|
}
|
|
|
|
|
|
|
|
get status() {
|
|
|
|
return this._status;
|
|
|
|
}
|
|
|
|
|
2015-02-11 11:10:31 -08:00
|
|
|
get valid() {
|
2015-02-24 11:59:10 -08:00
|
|
|
return this._status === VALID;
|
|
|
|
}
|
|
|
|
|
|
|
|
get errors() {
|
|
|
|
return this._errors;
|
|
|
|
}
|
|
|
|
|
2015-03-19 10:51:49 -07:00
|
|
|
get pristine() {
|
|
|
|
return this._pristine;
|
|
|
|
}
|
|
|
|
|
|
|
|
get dirty() {
|
|
|
|
return ! this.pristine;
|
|
|
|
}
|
|
|
|
|
2015-02-24 11:59:10 -08:00
|
|
|
setParent(parent){
|
|
|
|
this._parent = parent;
|
2015-02-11 11:10:31 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
_updateParent() {
|
|
|
|
if (isPresent(this._parent)){
|
2015-03-24 13:45:47 -07:00
|
|
|
this._parent._updateValue();
|
2015-02-11 11:10:31 -08:00
|
|
|
}
|
2015-02-03 07:27:09 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-02-25 15:10:27 -08:00
|
|
|
export class Control extends AbstractControl {
|
2015-03-19 14:21:40 -07:00
|
|
|
constructor(value:any, validator:Function = Validators.nullValidator) {
|
2015-02-25 15:10:27 -08:00
|
|
|
super(validator);
|
2015-03-24 13:45:47 -07:00
|
|
|
this._setValueErrorsStatus(value);
|
|
|
|
|
|
|
|
this._valueChangesController = ObservableWrapper.createController();
|
|
|
|
this.valueChanges = ObservableWrapper.createObservable(this._valueChangesController);
|
2015-02-03 07:27:09 -08:00
|
|
|
}
|
|
|
|
|
2015-02-25 15:10:27 -08:00
|
|
|
updateValue(value:any) {
|
2015-03-24 13:45:47 -07:00
|
|
|
this._setValueErrorsStatus(value);
|
2015-03-19 10:51:49 -07:00
|
|
|
this._pristine = false;
|
2015-03-24 13:45:47 -07:00
|
|
|
|
|
|
|
ObservableWrapper.callNext(this._valueChangesController, this._value);
|
|
|
|
|
2015-02-25 15:10:27 -08:00
|
|
|
this._updateParent();
|
2015-02-24 11:59:10 -08:00
|
|
|
}
|
|
|
|
|
2015-03-24 13:45:47 -07:00
|
|
|
_setValueErrorsStatus(value) {
|
|
|
|
this._value = value;
|
|
|
|
this._errors = this.validator(this);
|
|
|
|
this._status = isPresent(this._errors) ? INVALID : VALID;
|
2015-02-03 07:27:09 -08:00
|
|
|
}
|
2015-02-25 15:10:27 -08:00
|
|
|
}
|
2015-02-11 11:10:31 -08:00
|
|
|
|
2015-02-25 15:10:27 -08:00
|
|
|
export class ControlGroup extends AbstractControl {
|
|
|
|
controls;
|
2015-03-10 18:12:30 -07:00
|
|
|
optionals;
|
2015-02-24 11:59:10 -08:00
|
|
|
|
2015-03-19 14:21:40 -07:00
|
|
|
constructor(controls, optionals = null, validator:Function = Validators.group) {
|
2015-02-25 15:10:27 -08:00
|
|
|
super(validator);
|
|
|
|
this.controls = controls;
|
2015-03-10 18:12:30 -07:00
|
|
|
this.optionals = isPresent(optionals) ? optionals : {};
|
2015-03-24 13:45:47 -07:00
|
|
|
|
|
|
|
this._valueChangesController = ObservableWrapper.createController();
|
|
|
|
this.valueChanges = ObservableWrapper.createObservable(this._valueChangesController);
|
|
|
|
|
2015-02-25 15:10:27 -08:00
|
|
|
this._setParentForControls();
|
2015-03-24 13:45:47 -07:00
|
|
|
this._setValueErrorsStatus();
|
2015-02-11 11:10:31 -08:00
|
|
|
}
|
|
|
|
|
2015-03-10 18:12:30 -07:00
|
|
|
include(controlName:string) {
|
|
|
|
StringMapWrapper.set(this.optionals, controlName, true);
|
2015-03-24 13:45:47 -07:00
|
|
|
this._updateValue();
|
2015-03-10 18:12:30 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
exclude(controlName:string) {
|
|
|
|
StringMapWrapper.set(this.optionals, controlName, false);
|
2015-03-24 13:45:47 -07:00
|
|
|
this._updateValue();
|
2015-03-10 18:12:30 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
contains(controlName:string) {
|
|
|
|
var c = StringMapWrapper.contains(this.controls, controlName);
|
|
|
|
return c && this._included(controlName);
|
|
|
|
}
|
|
|
|
|
2015-02-11 11:10:31 -08:00
|
|
|
_setParentForControls() {
|
|
|
|
StringMapWrapper.forEach(this.controls, (control, name) => {
|
2015-02-24 11:59:10 -08:00
|
|
|
control.setParent(this);
|
2015-02-11 11:10:31 -08:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2015-03-24 13:45:47 -07:00
|
|
|
_updateValue() {
|
|
|
|
this._setValueErrorsStatus();
|
|
|
|
this._pristine = false;
|
|
|
|
|
|
|
|
ObservableWrapper.callNext(this._valueChangesController, this._value);
|
|
|
|
|
|
|
|
this._updateParent();
|
|
|
|
}
|
|
|
|
|
|
|
|
_setValueErrorsStatus() {
|
|
|
|
this._value = this._reduceValue();
|
|
|
|
this._errors = this.validator(this);
|
|
|
|
this._status = isPresent(this._errors) ? INVALID : VALID;
|
2015-02-24 11:59:10 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
_reduceValue() {
|
2015-03-19 10:51:49 -07:00
|
|
|
return this._reduceChildren({}, (acc, control, name) => {
|
|
|
|
acc[name] = control.value;
|
|
|
|
return acc;
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
_reduceChildren(initValue, fn:Function) {
|
|
|
|
var res = initValue;
|
2015-02-24 11:59:10 -08:00
|
|
|
StringMapWrapper.forEach(this.controls, (control, name) => {
|
2015-03-10 18:12:30 -07:00
|
|
|
if (this._included(name)) {
|
2015-03-19 10:51:49 -07:00
|
|
|
res = fn(res, control, name);
|
2015-02-24 11:59:10 -08:00
|
|
|
}
|
|
|
|
});
|
2015-03-19 10:51:49 -07:00
|
|
|
return res;
|
2015-02-11 11:10:31 -08:00
|
|
|
}
|
|
|
|
|
2015-03-10 18:12:30 -07:00
|
|
|
_included(controlName:string):boolean {
|
|
|
|
var isOptional = StringMapWrapper.contains(this.optionals, controlName);
|
|
|
|
return !isOptional || StringMapWrapper.get(this.optionals, controlName);
|
2015-02-24 11:59:10 -08:00
|
|
|
}
|
2015-03-25 10:51:05 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
export class ControlArray extends AbstractControl {
|
|
|
|
controls:List;
|
|
|
|
|
|
|
|
constructor(controls:List, validator:Function = Validators.array) {
|
|
|
|
super(validator);
|
|
|
|
this.controls = controls;
|
|
|
|
|
|
|
|
this._valueChangesController = ObservableWrapper.createController();
|
|
|
|
this.valueChanges = ObservableWrapper.createObservable(this._valueChangesController);
|
|
|
|
|
|
|
|
this._setParentForControls();
|
|
|
|
this._setValueErrorsStatus();
|
|
|
|
}
|
|
|
|
|
|
|
|
at(index:number) {
|
|
|
|
return this.controls[index];
|
|
|
|
}
|
|
|
|
|
|
|
|
push(control) {
|
|
|
|
ListWrapper.push(this.controls, control);
|
|
|
|
control.setParent(this);
|
|
|
|
this._updateValue();
|
|
|
|
}
|
|
|
|
|
|
|
|
insert(index:number, control) {
|
|
|
|
ListWrapper.insert(this.controls, index, control);
|
|
|
|
control.setParent(this);
|
|
|
|
this._updateValue();
|
|
|
|
}
|
|
|
|
|
|
|
|
removeAt(index:number) {
|
|
|
|
ListWrapper.removeAt(this.controls, index);
|
|
|
|
this._updateValue();
|
|
|
|
}
|
|
|
|
|
|
|
|
get length() {
|
|
|
|
return this.controls.length;
|
|
|
|
}
|
|
|
|
|
|
|
|
_updateValue() {
|
|
|
|
this._setValueErrorsStatus();
|
|
|
|
this._pristine = false;
|
|
|
|
|
|
|
|
ObservableWrapper.callNext(this._valueChangesController, this._value);
|
|
|
|
|
|
|
|
this._updateParent();
|
|
|
|
}
|
|
|
|
|
|
|
|
_setParentForControls() {
|
|
|
|
ListWrapper.forEach(this.controls, (control) => {
|
|
|
|
control.setParent(this);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
_setValueErrorsStatus() {
|
|
|
|
this._value = ListWrapper.map(this.controls, (c) => c.value);
|
|
|
|
this._errors = this.validator(this);
|
|
|
|
this._status = isPresent(this._errors) ? INVALID : VALID;
|
|
|
|
}
|
2015-03-24 11:01:26 -04:00
|
|
|
}
|