refactor(forms): wrapped all validators into the Validator class
This commit is contained in:
parent
41b53e71e1
commit
a12dc7d75a
|
@ -4,7 +4,7 @@ import {DOM} from 'angular2/src/dom/dom_adapter';
|
||||||
import {isBlank, isPresent, isString, CONST} from 'angular2/src/facade/lang';
|
import {isBlank, isPresent, isString, CONST} from 'angular2/src/facade/lang';
|
||||||
import {StringMapWrapper, ListWrapper} from 'angular2/src/facade/collection';
|
import {StringMapWrapper, ListWrapper} from 'angular2/src/facade/collection';
|
||||||
import {ControlGroup, Control} from './model';
|
import {ControlGroup, Control} from './model';
|
||||||
import * as validators from './validators';
|
import {Validators} from './validators';
|
||||||
|
|
||||||
@CONST()
|
@CONST()
|
||||||
export class ControlValueAccessor {
|
export class ControlValueAccessor {
|
||||||
|
@ -79,7 +79,7 @@ export class ControlDirective {
|
||||||
this._el = el;
|
this._el = el;
|
||||||
this.controlName = null;
|
this.controlName = null;
|
||||||
this.type = null;
|
this.type = null;
|
||||||
this.validator = validators.nullValidator;
|
this.validator = Validators.nullValidator;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: vsavkin this should be moved into the constructor once static bindings
|
// TODO: vsavkin this should be moved into the constructor once static bindings
|
||||||
|
@ -92,7 +92,7 @@ export class ControlDirective {
|
||||||
this._groupDirective.addDirective(this);
|
this._groupDirective.addDirective(this);
|
||||||
|
|
||||||
var c = this._control();
|
var c = this._control();
|
||||||
c.validator = validators.compose([c.validator, this.validator]);
|
c.validator = Validators.compose([c.validator, this.validator]);
|
||||||
|
|
||||||
if (isBlank(this.valueAccessor)) {
|
if (isBlank(this.valueAccessor)) {
|
||||||
this.valueAccessor = controlValueAccessorFor(this.type);
|
this.valueAccessor = controlValueAccessorFor(this.type);
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import {isPresent} from 'angular2/src/facade/lang';
|
import {isPresent} from 'angular2/src/facade/lang';
|
||||||
import {StringMap, StringMapWrapper} from 'angular2/src/facade/collection';
|
import {StringMap, StringMapWrapper} from 'angular2/src/facade/collection';
|
||||||
import {nullValidator, controlGroupValidator} from './validators';
|
import {Validators} from './validators';
|
||||||
|
|
||||||
export const VALID = "VALID";
|
export const VALID = "VALID";
|
||||||
export const INVALID = "INVALID";
|
export const INVALID = "INVALID";
|
||||||
|
@ -26,7 +26,7 @@ export class AbstractControl {
|
||||||
_parent:ControlGroup;
|
_parent:ControlGroup;
|
||||||
validator:Function;
|
validator:Function;
|
||||||
|
|
||||||
constructor(validator:Function = nullValidator) {
|
constructor(validator:Function) {
|
||||||
this.validator = validator;
|
this.validator = validator;
|
||||||
this._updateNeeded = true;
|
this._updateNeeded = true;
|
||||||
this._pristine = true;
|
this._pristine = true;
|
||||||
|
@ -76,7 +76,7 @@ export class AbstractControl {
|
||||||
}
|
}
|
||||||
|
|
||||||
export class Control extends AbstractControl {
|
export class Control extends AbstractControl {
|
||||||
constructor(value:any, validator:Function = nullValidator) {
|
constructor(value:any, validator:Function = Validators.nullValidator) {
|
||||||
super(validator);
|
super(validator);
|
||||||
this._value = value;
|
this._value = value;
|
||||||
}
|
}
|
||||||
|
@ -101,7 +101,7 @@ export class ControlGroup extends AbstractControl {
|
||||||
controls;
|
controls;
|
||||||
optionals;
|
optionals;
|
||||||
|
|
||||||
constructor(controls, optionals = null, validator:Function = controlGroupValidator) {
|
constructor(controls, optionals = null, validator:Function = Validators.group) {
|
||||||
super(validator);
|
super(validator);
|
||||||
this.controls = controls;
|
this.controls = controls;
|
||||||
this.optionals = isPresent(optionals) ? optionals : {};
|
this.optionals = isPresent(optionals) ? optionals : {};
|
||||||
|
|
|
@ -1,13 +1,12 @@
|
||||||
import {Decorator} from 'angular2/angular2';
|
import {Decorator} from 'angular2/angular2';
|
||||||
|
|
||||||
import {ControlDirective} from 'angular2/forms';
|
import {ControlDirective, Validators} from 'angular2/forms';
|
||||||
import * as validators from 'angular2/forms';
|
|
||||||
|
|
||||||
@Decorator({
|
@Decorator({
|
||||||
selector: '[required]'
|
selector: '[required]'
|
||||||
})
|
})
|
||||||
export class RequiredValidatorDirective {
|
export class RequiredValidatorDirective {
|
||||||
constructor(c:ControlDirective) {
|
constructor(c:ControlDirective) {
|
||||||
c.validator = validators.compose([c.validator, validators.required]);
|
c.validator = Validators.compose([c.validator, Validators.required]);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -3,35 +3,37 @@ import {List, ListWrapper, StringMapWrapper} from 'angular2/src/facade/collectio
|
||||||
|
|
||||||
import * as modelModule from './model';
|
import * as modelModule from './model';
|
||||||
|
|
||||||
export function required(c:modelModule.Control) {
|
export class Validators {
|
||||||
return isBlank(c.value) || c.value == "" ? {"required" : true} : null;
|
static required(c:modelModule.Control) {
|
||||||
}
|
return isBlank(c.value) || c.value == "" ? {"required": true} : null;
|
||||||
|
}
|
||||||
|
|
||||||
export function nullValidator(c:modelModule.Control) {
|
static nullValidator(c:modelModule.Control) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function compose(validators:List<Function>):Function {
|
static compose(validators:List<Function>):Function {
|
||||||
return function(c:modelModule.Control) {
|
return function (c:modelModule.Control) {
|
||||||
var res = ListWrapper.reduce(validators, (res, validator) => {
|
var res = ListWrapper.reduce(validators, (res, validator) => {
|
||||||
var errors = validator(c);
|
var errors = validator(c);
|
||||||
return isPresent(errors) ? StringMapWrapper.merge(res, errors) : res;
|
return isPresent(errors) ? StringMapWrapper.merge(res, errors) : res;
|
||||||
}, {});
|
}, {});
|
||||||
|
return StringMapWrapper.isEmpty(res) ? null : res;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static group(c:modelModule.ControlGroup) {
|
||||||
|
var res = {};
|
||||||
|
StringMapWrapper.forEach(c.controls, (control, name) => {
|
||||||
|
if (c.contains(name) && isPresent(control.errors)) {
|
||||||
|
StringMapWrapper.forEach(control.errors, (value, error) => {
|
||||||
|
if (!StringMapWrapper.contains(res, error)) {
|
||||||
|
res[error] = [];
|
||||||
|
}
|
||||||
|
ListWrapper.push(res[error], control);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
return StringMapWrapper.isEmpty(res) ? null : res;
|
return StringMapWrapper.isEmpty(res) ? null : res;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function controlGroupValidator(c:modelModule.ControlGroup) {
|
|
||||||
var res = {};
|
|
||||||
StringMapWrapper.forEach(c.controls, (control, name) => {
|
|
||||||
if (c.contains(name) && isPresent(control.errors)) {
|
|
||||||
StringMapWrapper.forEach(control.errors, (value, error) => {
|
|
||||||
if (! StringMapWrapper.contains(res, error)) {
|
|
||||||
res[error] = [];
|
|
||||||
}
|
|
||||||
ListWrapper.push(res[error], control);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return StringMapWrapper.isEmpty(res) ? null : res;
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
import {ddescribe, describe, it, iit, xit, expect, beforeEach, afterEach, el} from 'angular2/test_lib';
|
import {ddescribe, describe, it, iit, xit, expect, beforeEach, afterEach, el} from 'angular2/test_lib';
|
||||||
import {Control, FormBuilder} from 'angular2/forms';
|
import {Control, FormBuilder, Validators} from 'angular2/forms';
|
||||||
import * as validations from 'angular2/forms';
|
|
||||||
|
|
||||||
export function main() {
|
export function main() {
|
||||||
describe("Form Builder", () => {
|
describe("Form Builder", () => {
|
||||||
|
@ -21,21 +20,21 @@ export function main() {
|
||||||
it("should create controls from an array", () => {
|
it("should create controls from an array", () => {
|
||||||
var g = b.group({
|
var g = b.group({
|
||||||
"login": ["some value"],
|
"login": ["some value"],
|
||||||
"password": ["some value", validations.required]
|
"password": ["some value", Validators.required]
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(g.controls["login"].value).toEqual("some value");
|
expect(g.controls["login"].value).toEqual("some value");
|
||||||
expect(g.controls["password"].value).toEqual("some value");
|
expect(g.controls["password"].value).toEqual("some value");
|
||||||
expect(g.controls["password"].validator).toEqual(validations.required);
|
expect(g.controls["password"].validator).toEqual(Validators.required);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should use controls", () => {
|
it("should use controls", () => {
|
||||||
var g = b.group({
|
var g = b.group({
|
||||||
"login": b.control("some value", validations.required)
|
"login": b.control("some value", Validators.required)
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(g.controls["login"].value).toEqual("some value");
|
expect(g.controls["login"].value).toEqual("some value");
|
||||||
expect(g.controls["login"].validator).toBe(validations.required);
|
expect(g.controls["login"].validator).toBe(Validators.required);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should create groups with optional controls", () => {
|
it("should create groups with optional controls", () => {
|
||||||
|
@ -49,17 +48,17 @@ export function main() {
|
||||||
it("should create groups with a custom validator", () => {
|
it("should create groups with a custom validator", () => {
|
||||||
var g = b.group({
|
var g = b.group({
|
||||||
"login": "some value"
|
"login": "some value"
|
||||||
}, {"validator": validations.nullValidator});
|
}, {"validator": Validators.nullValidator});
|
||||||
|
|
||||||
expect(g.validator).toBe(validations.nullValidator);
|
expect(g.validator).toBe(Validators.nullValidator);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should use default validators when no validators are provided", () => {
|
it("should use default validators when no validators are provided", () => {
|
||||||
var g = b.group({
|
var g = b.group({
|
||||||
"login": "some value"
|
"login": "some value"
|
||||||
});
|
});
|
||||||
expect(g.controls["login"].validator).toBe(validations.nullValidator);
|
expect(g.controls["login"].validator).toBe(Validators.nullValidator);
|
||||||
expect(g.validator).toBe(validations.controlGroupValidator);
|
expect(g.validator).toBe(Validators.group);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
|
@ -31,9 +31,7 @@ import {Injector} from 'angular2/di';
|
||||||
|
|
||||||
import {Component, Decorator, Template} from 'angular2/angular2';
|
import {Component, Decorator, Template} from 'angular2/angular2';
|
||||||
import {ControlGroupDirective, ControlDirective, Control, ControlGroup, OptionalControl,
|
import {ControlGroupDirective, ControlDirective, Control, ControlGroup, OptionalControl,
|
||||||
ControlValueAccessor, RequiredValidatorDirective} from 'angular2/forms';
|
ControlValueAccessor, RequiredValidatorDirective, Validators} from 'angular2/forms';
|
||||||
|
|
||||||
import * as validators from 'angular2/src/forms/validators';
|
|
||||||
|
|
||||||
export function main() {
|
export function main() {
|
||||||
function detectChanges(view) {
|
function detectChanges(view) {
|
||||||
|
@ -261,7 +259,7 @@ export function main() {
|
||||||
}));
|
}));
|
||||||
|
|
||||||
it("should use validators defined in the model", inject([AsyncTestCompleter], (async) => {
|
it("should use validators defined in the model", inject([AsyncTestCompleter], (async) => {
|
||||||
var form = new ControlGroup({"login": new Control("aa", validators.required)});
|
var form = new ControlGroup({"login": new Control("aa", Validators.required)});
|
||||||
var ctx = new MyComp(form);
|
var ctx = new MyComp(form);
|
||||||
|
|
||||||
var t = `<div [control-group]="form">
|
var t = `<div [control-group]="form">
|
||||||
|
|
|
@ -1,24 +1,23 @@
|
||||||
import {ddescribe, describe, it, iit, xit, expect, beforeEach, afterEach, el} from 'angular2/test_lib';
|
import {ddescribe, describe, it, iit, xit, expect, beforeEach, afterEach, el} from 'angular2/test_lib';
|
||||||
import {ControlGroup, Control, OptionalControl} from 'angular2/forms';
|
import {ControlGroup, Control, OptionalControl, Validators} from 'angular2/forms';
|
||||||
import * as validations from 'angular2/forms';
|
|
||||||
|
|
||||||
export function main() {
|
export function main() {
|
||||||
describe("Form Model", () => {
|
describe("Form Model", () => {
|
||||||
describe("Control", () => {
|
describe("Control", () => {
|
||||||
describe("validator", () => {
|
describe("validator", () => {
|
||||||
it("should run validator with the initial value", () => {
|
it("should run validator with the initial value", () => {
|
||||||
var c = new Control("value", validations.required);
|
var c = new Control("value", Validators.required);
|
||||||
expect(c.valid).toEqual(true);
|
expect(c.valid).toEqual(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should rerun the validator when the value changes", () => {
|
it("should rerun the validator when the value changes", () => {
|
||||||
var c = new Control("value", validations.required);
|
var c = new Control("value", Validators.required);
|
||||||
c.updateValue(null);
|
c.updateValue(null);
|
||||||
expect(c.valid).toEqual(false);
|
expect(c.valid).toEqual(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should return errors", () => {
|
it("should return errors", () => {
|
||||||
var c = new Control(null, validations.required);
|
var c = new Control(null, Validators.required);
|
||||||
expect(c.errors).toEqual({"required" : true});
|
expect(c.errors).toEqual({"required" : true});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -83,7 +82,7 @@ export function main() {
|
||||||
describe("validator", () => {
|
describe("validator", () => {
|
||||||
it("should run the validator with the initial value (valid)", () => {
|
it("should run the validator with the initial value (valid)", () => {
|
||||||
var g = new ControlGroup({
|
var g = new ControlGroup({
|
||||||
"one": new Control('value', validations.required)
|
"one": new Control('value', Validators.required)
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(g.valid).toEqual(true);
|
expect(g.valid).toEqual(true);
|
||||||
|
@ -92,7 +91,7 @@ export function main() {
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should run the validator with the initial value (invalid)", () => {
|
it("should run the validator with the initial value (invalid)", () => {
|
||||||
var one = new Control(null, validations.required);
|
var one = new Control(null, Validators.required);
|
||||||
var g = new ControlGroup({"one": one});
|
var g = new ControlGroup({"one": one});
|
||||||
|
|
||||||
expect(g.valid).toEqual(false);
|
expect(g.valid).toEqual(false);
|
||||||
|
@ -101,7 +100,7 @@ export function main() {
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should run the validator with the value changes", () => {
|
it("should run the validator with the value changes", () => {
|
||||||
var c = new Control(null, validations.required);
|
var c = new Control(null, Validators.required);
|
||||||
var g = new ControlGroup({"one": c});
|
var g = new ControlGroup({"one": c});
|
||||||
|
|
||||||
c.updateValue("some value");
|
c.updateValue("some value");
|
||||||
|
@ -174,10 +173,10 @@ export function main() {
|
||||||
expect(group.value).toEqual({"required" : "requiredValue", "optional" : "optionalValue"});
|
expect(group.value).toEqual({"required" : "requiredValue", "optional" : "optionalValue"});
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should not run validations on an inactive component", () => {
|
it("should not run Validators on an inactive component", () => {
|
||||||
var group = new ControlGroup({
|
var group = new ControlGroup({
|
||||||
"required": new Control("requiredValue", validations.required),
|
"required": new Control("requiredValue", Validators.required),
|
||||||
"optional": new Control("", validations.required)
|
"optional": new Control("", Validators.required)
|
||||||
}, {
|
}, {
|
||||||
"optional": false
|
"optional": false
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import {ddescribe, describe, it, iit, xit, expect, beforeEach, afterEach, el} from 'angular2/test_lib';
|
import {ddescribe, describe, it, iit, xit, expect, beforeEach, afterEach, el} from 'angular2/test_lib';
|
||||||
import {ControlGroup, Control, required, compose, controlGroupValidator, nullValidator} from 'angular2/forms';
|
import {ControlGroup, Control, Validators} from 'angular2/forms';
|
||||||
|
|
||||||
export function main() {
|
export function main() {
|
||||||
function validator(key:string, error:any){
|
function validator(key:string, error:any){
|
||||||
|
@ -13,31 +13,31 @@ export function main() {
|
||||||
describe("Validators", () => {
|
describe("Validators", () => {
|
||||||
describe("required", () => {
|
describe("required", () => {
|
||||||
it("should error on an empty string", () => {
|
it("should error on an empty string", () => {
|
||||||
expect(required(new Control(""))).toEqual({"required" : true});
|
expect(Validators.required(new Control(""))).toEqual({"required" : true});
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should error on null", () => {
|
it("should error on null", () => {
|
||||||
expect(required(new Control(null))).toEqual({"required" : true});
|
expect(Validators.required(new Control(null))).toEqual({"required" : true});
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should not error on a non-empty string", () => {
|
it("should not error on a non-empty string", () => {
|
||||||
expect(required(new Control("not empty"))).toEqual(null);
|
expect(Validators.required(new Control("not empty"))).toEqual(null);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("compose", () => {
|
describe("compose", () => {
|
||||||
it("should collect errors from all the validators", () => {
|
it("should collect errors from all the validators", () => {
|
||||||
var c = compose([validator("a", true), validator("b", true)]);
|
var c = Validators.compose([validator("a", true), validator("b", true)]);
|
||||||
expect(c(new Control(""))).toEqual({"a" : true, "b" : true});
|
expect(c(new Control(""))).toEqual({"a" : true, "b" : true});
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should run validators left to right", () => {
|
it("should run validators left to right", () => {
|
||||||
var c = compose([validator("a", 1), validator("a", 2)]);
|
var c = Validators.compose([validator("a", 1), validator("a", 2)]);
|
||||||
expect(c(new Control(""))).toEqual({"a" : 2});
|
expect(c(new Control(""))).toEqual({"a" : 2});
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should return null when no errors", () => {
|
it("should return null when no errors", () => {
|
||||||
var c = compose([nullValidator, nullValidator]);
|
var c = Validators.compose([Validators.nullValidator, Validators.nullValidator]);
|
||||||
expect(c(new Control(""))).toEqual(null);
|
expect(c(new Control(""))).toEqual(null);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -48,7 +48,7 @@ export function main() {
|
||||||
var two = new Control("one", validator("b", true));
|
var two = new Control("one", validator("b", true));
|
||||||
var g = new ControlGroup({"one" : one, "two" : two});
|
var g = new ControlGroup({"one" : one, "two" : two});
|
||||||
|
|
||||||
expect(controlGroupValidator(g)).toEqual({
|
expect(Validators.group(g)).toEqual({
|
||||||
"a" : [one],
|
"a" : [one],
|
||||||
"b" : [two]
|
"b" : [two]
|
||||||
});
|
});
|
||||||
|
@ -59,7 +59,7 @@ export function main() {
|
||||||
var two = new Control("two");
|
var two = new Control("two");
|
||||||
var g = new ControlGroup({"one" : one, "two" : two});
|
var g = new ControlGroup({"one" : one, "two" : two});
|
||||||
|
|
||||||
expect(controlGroupValidator(g)).toEqual({
|
expect(Validators.group(g)).toEqual({
|
||||||
"a": [one]
|
"a": [one]
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -69,7 +69,7 @@ export function main() {
|
||||||
"one" : new Control("one")
|
"one" : new Control("one")
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(controlGroupValidator(g)).toEqual(null);
|
expect(Validators.group(g)).toEqual(null);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in New Issue