feat(validators): Allow errors at both the group/array level or their children

Allow ControlGroups and ControlArrays to contain errors from their level, and
errors from their children. [Design Doc](https://docs.google.com/document/d/1EnJ3-_iFpVKFz1ifN1LkXSGQ7h3A72OQGry2g8eo7IA/edit?pli=1#heading=h.j53rt81eegm4)

BREAKING CHANGE: errors format has changed from validators. Now errors from
a control or an array's children are prefixed with 'controls' while errors
from the object itself are left at the root level.
Example:
Given a Control group as follows:
var group = new ControlGroup({
  login: new Control("", required),
  password: new Control("", required),
  passwordConfirm: new Control("", required)
});

Before:
group.errors

{
  login: {required: true},
  password: {required: true},
  passwordConfirm: {required: true},
}

After:
group.errors

{
  controls: {
    login: {required: true},
    password: {required: true},
    passwordConfirm: {required: true},
  }
}
This commit is contained in:
Ted Sander
2015-10-16 16:13:14 -07:00
committed by vsavkin
parent c9fba3fa1f
commit 28d88c5b12
3 changed files with 81 additions and 26 deletions

View File

@ -46,7 +46,7 @@ export class Validators {
static compose(validators: Function[]): Function {
if (isBlank(validators)) return Validators.nullValidator;
return function(control: modelModule.Control) {
return function(control: modelModule.AbstractControl) {
var res = ListWrapper.reduce(validators, (res, validator) => {
var errors = validator(control);
return isPresent(errors) ? StringMapWrapper.merge(<any>res, <any>errors) : res;
@ -55,33 +55,25 @@ export class Validators {
};
}
static group(group: modelModule.ControlGroup): {[key: string]: any[]} {
static group(group: modelModule.ControlGroup): {[key: string]: any} {
var res: {[key: string]: any[]} = {};
StringMapWrapper.forEach(group.controls, (control, name) => {
if (group.contains(name) && isPresent(control.errors)) {
Validators._mergeErrors(control, res);
res[name] = control.errors;
}
});
return StringMapWrapper.isEmpty(res) ? null : res;
return StringMapWrapper.isEmpty(res) ? null : {'controls': res};
}
static array(array: modelModule.ControlArray): {[key: string]: any[]} {
var res: {[key: string]: any[]} = {};
static array(array: modelModule.ControlArray): {[key: string]: any} {
var res: any[] = [];
var anyErrors: boolean = false;
array.controls.forEach((control) => {
res.push(control.errors);
if (isPresent(control.errors)) {
Validators._mergeErrors(control, res);
anyErrors = true;
}
});
return StringMapWrapper.isEmpty(res) ? null : res;
}
static _mergeErrors(control: modelModule.AbstractControl, res: {[key: string]: any[]}): void {
StringMapWrapper.forEach(control.errors, (value, error) => {
if (!StringMapWrapper.contains(res, error)) {
res[error] = [];
}
var current: any[] = res[error];
current.push(control);
});
return anyErrors ? {'controls': res} : null;
}
}