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
@@ -192,7 +192,7 @@ export function main() {
expect(g.valid).toEqual(false);
expect(g.errors).toEqual({"required": [one]});
expect(g.errors).toEqual({"controls": {"one": {"required": true}}});
});
it("should run the validator with the value changes", () => {
@@ -445,7 +445,7 @@ export function main() {
]);
expect(a.valid).toBe(false);
expect(a.errors).toEqual({"required": [a.controls[1]]});
expect(a.errors).toEqual({"controls": [null, {"required": true}, null]});
});
it("should run the validator when the value changes", () => {
@@ -9,11 +9,11 @@ import {
afterEach,
el
} from 'angular2/testing_internal';
import {ControlGroup, Control, Validators} from 'angular2/core';
import {ControlGroup, Control, Validators, AbstractControl, ControlArray} from 'angular2/core';
export function main() {
function validator(key: string, error: any) {
return function(c: Control) {
return function(c: AbstractControl) {
var r = {};
r[key] = error;
return r;
@@ -87,10 +87,10 @@ export function main() {
describe("controlGroupValidator", () => {
it("should collect errors from the child controls", () => {
var one = new Control("one", validator("a", true));
var two = new Control("one", validator("b", true));
var two = new Control("two", validator("b", true));
var g = new ControlGroup({"one": one, "two": two});
expect(Validators.group(g)).toEqual({"a": [one], "b": [two]});
expect(Validators.group(g)).toEqual({"controls": {"one": {"a": true}, "two": {"b": true}}});
});
it("should not include controls that have no errors", () => {
@@ -98,7 +98,7 @@ export function main() {
var two = new Control("two");
var g = new ControlGroup({"one": one, "two": two});
expect(Validators.group(g)).toEqual({"a": [one]});
expect(Validators.group(g)).toEqual({"controls": {"one": {"a": true}}});
});
it("should return null when no errors", () => {
@@ -106,6 +106,69 @@ export function main() {
expect(Validators.group(g)).toEqual(null);
});
it("should return control errors mixed with group errors", () => {
var one = new Control("one", validator("a", true));
var g = new ControlGroup({"one": one}, null,
Validators.compose([validator("b", true), Validators.group]));
expect(g.validator(g)).toEqual({"b": true, "controls": {"one": {"a": true}}});
});
it("should return nested control group errors mixed with group errors", () => {
var one = new Control("one", validator("a", true));
var g = new ControlGroup({"one": one}, null,
Validators.compose([validator("b", true), Validators.group]));
var two = new Control("two", validator("c", true));
var gTwo = new ControlGroup({"two": two, "group": g});
expect(gTwo.validator(gTwo))
.toEqual({
"controls":
{"two": {"c": true}, "group": {"b": true, "controls": {"one": {"a": true}}}}
});
});
});
describe("controlArrayValidator", () => {
it("should collect errors from the child controls", () => {
var one = new Control("one", validator("a", true));
var two = new Control("two", validator("b", true));
var a = new ControlArray([one, two]);
expect(Validators.array(a)).toEqual({"controls": [{"a": true}, {"b": true}]});
});
it("should not include controls that have no errors", () => {
var one = new Control("one");
var two = new Control("two", validator("a", true));
var three = new Control("three");
var a = new ControlArray([one, two, three]);
expect(Validators.array(a)).toEqual({"controls": [null, {"a": true}, null]});
});
it("should return null when no errors", () => {
var a = new ControlArray([new Control("one")]);
expect(Validators.array(a)).toEqual(null);
});
it("should return control errors mixed with group errors", () => {
var one = new Control("one", validator("a", true));
var a =
new ControlArray([one], Validators.compose([validator("b", true), Validators.array]));
expect(a.validator(a)).toEqual({"b": true, "controls": [{"a": true}]});
});
it("should return nested array errors ", () => {
var one = new Control("one", validator("a", true));
var a = new ControlArray([one]);
var a2 = new ControlArray([a]);
expect(Validators.array(a2)).toEqual({"controls": [{"controls": [{"a": true}]}]});
});
});
});
}
}