diff --git a/modules/angular2/forms.ts b/modules/angular2/forms.ts index abee111adb..d49a41da01 100644 --- a/modules/angular2/forms.ts +++ b/modules/angular2/forms.ts @@ -32,8 +32,8 @@ export { SelectControlValueAccessor } from './src/forms/directives/select_control_value_accessor'; export {FORM_DIRECTIVES} from './src/forms/directives'; -export {Validators} from './src/forms/validators'; -export {NgValidator, NgRequiredValidator} from './src/forms/directives/validators'; +export {NG_VALIDATORS, Validators} from './src/forms/validators'; +export {DefaultValidators} from './src/forms/directives/validators'; export {FormBuilder} from './src/forms/form_builder'; import {FormBuilder} from './src/forms/form_builder'; diff --git a/modules/angular2/src/forms/directives.ts b/modules/angular2/src/forms/directives.ts index d21cc35497..9af6341461 100644 --- a/modules/angular2/src/forms/directives.ts +++ b/modules/angular2/src/forms/directives.ts @@ -11,7 +11,7 @@ import { SelectControlValueAccessor, NgSelectOption } from './directives/select_control_value_accessor'; -import {NgRequiredValidator} from './directives/validators'; +import {DefaultValidators} from './directives/validators'; export {NgControlName} from './directives/ng_control_name'; export {NgFormControl} from './directives/ng_form_control'; @@ -27,7 +27,7 @@ export { SelectControlValueAccessor, NgSelectOption } from './directives/select_control_value_accessor'; -export {NgValidator, NgRequiredValidator} from './directives/validators'; +export {DefaultValidators} from './directives/validators'; /** * @@ -49,5 +49,5 @@ export const FORM_DIRECTIVES: Type[] = CONST_EXPR([ CheckboxControlValueAccessor, SelectControlValueAccessor, - NgRequiredValidator + DefaultValidators ]); diff --git a/modules/angular2/src/forms/directives/ng_control_name.ts b/modules/angular2/src/forms/directives/ng_control_name.ts index e533ccf6b7..deab9d6cc1 100644 --- a/modules/angular2/src/forms/directives/ng_control_name.ts +++ b/modules/angular2/src/forms/directives/ng_control_name.ts @@ -4,13 +4,14 @@ import {StringMap} from 'angular2/src/core/facade/collection'; import {QueryList} from 'angular2/core'; import {Query, Directive, LifecycleEvent} from 'angular2/metadata'; -import {forwardRef, Host, SkipSelf, Binding, Inject} from 'angular2/di'; +import {forwardRef, Host, SkipSelf, Binding, Inject, Optional} from 'angular2/di'; import {ControlContainer} from './control_container'; import {NgControl} from './ng_control'; -import {NgValidator} from './validators'; -import {controlPath, composeNgValidator, isPropertyUpdated} from './shared'; +import {controlPath, isPropertyUpdated} from './shared'; import {Control} from '../model'; +import {Validators, NG_VALIDATORS} from '../validators'; + const controlNameBinding = CONST_EXPR(new Binding(NgControl, {toAlias: forwardRef(() => NgControlName)})); @@ -84,15 +85,15 @@ export class NgControlName extends NgControl { update = new EventEmitter(); model: any; viewModel: any; - ngValidators: QueryList; + validators: Function[]; _added = false; // Scope the query once https://github.com/angular/angular/issues/2603 is fixed constructor(@Host() @SkipSelf() parent: ControlContainer, - @Query(NgValidator) ngValidators: QueryList) { + @Optional() @Inject(NG_VALIDATORS) validators: Function[]) { super(); this._parent = parent; - this.ngValidators = ngValidators; + this.validators = validators; } onChanges(c: StringMap) { @@ -119,5 +120,5 @@ export class NgControlName extends NgControl { get control(): Control { return this.formDirective.getControl(this); } - get validator(): Function { return composeNgValidator(this.ngValidators); } + get validator(): Function { return Validators.compose(this.validators); } } diff --git a/modules/angular2/src/forms/directives/ng_form_control.ts b/modules/angular2/src/forms/directives/ng_form_control.ts index 587a3b9be4..902887b4a6 100644 --- a/modules/angular2/src/forms/directives/ng_form_control.ts +++ b/modules/angular2/src/forms/directives/ng_form_control.ts @@ -3,12 +3,12 @@ import {EventEmitter, ObservableWrapper} from 'angular2/src/core/facade/async'; import {QueryList} from 'angular2/core'; import {Query, Directive, LifecycleEvent} from 'angular2/metadata'; -import {forwardRef, Binding} from 'angular2/di'; +import {forwardRef, Binding, Inject, Optional} from 'angular2/di'; import {NgControl} from './ng_control'; import {Control} from '../model'; -import {NgValidator} from './validators'; -import {setUpControl, composeNgValidator, isPropertyUpdated} from './shared'; +import {Validators, NG_VALIDATORS} from '../validators'; +import {setUpControl, isPropertyUpdated} from './shared'; const formControlBinding = CONST_EXPR(new Binding(NgControl, {toAlias: forwardRef(() => NgFormControl)})); @@ -72,12 +72,11 @@ export class NgFormControl extends NgControl { _added = false; model: any; viewModel: any; - ngValidators: QueryList; + validators: Function[]; - // Scope the query once https://github.com/angular/angular/issues/2603 is fixed - constructor(@Query(NgValidator) ngValidators: QueryList) { + constructor(@Optional() @Inject(NG_VALIDATORS) validators: Function[]) { super(); - this.ngValidators = ngValidators; + this.validators = validators; } onChanges(c: StringMap) { @@ -95,7 +94,7 @@ export class NgFormControl extends NgControl { get control(): Control { return this.form; } - get validator(): Function { return composeNgValidator(this.ngValidators); } + get validator(): Function { return Validators.compose(this.validators); } viewToModelUpdate(newValue: any): void { this.viewModel = newValue; diff --git a/modules/angular2/src/forms/directives/ng_model.ts b/modules/angular2/src/forms/directives/ng_model.ts index 16337ecde3..04bf7dbfe6 100644 --- a/modules/angular2/src/forms/directives/ng_model.ts +++ b/modules/angular2/src/forms/directives/ng_model.ts @@ -3,12 +3,12 @@ import {EventEmitter, ObservableWrapper} from 'angular2/src/core/facade/async'; import {QueryList} from 'angular2/core'; import {Query, Directive, LifecycleEvent} from 'angular2/metadata'; -import {forwardRef, Binding} from 'angular2/di'; +import {forwardRef, Binding, Inject, Optional} from 'angular2/di'; import {NgControl} from './ng_control'; import {Control} from '../model'; -import {NgValidator} from './validators'; -import {setUpControl, composeNgValidator, isPropertyUpdated} from './shared'; +import {Validators, NG_VALIDATORS} from '../validators'; +import {setUpControl, isPropertyUpdated} from './shared'; const formControlBinding = CONST_EXPR(new Binding(NgControl, {toAlias: forwardRef(() => NgModel)})); @@ -42,12 +42,11 @@ export class NgModel extends NgControl { update = new EventEmitter(); model: any; viewModel: any; - ngValidators: QueryList; + validators: Function[]; - // Scope the query once https://github.com/angular/angular/issues/2603 is fixed - constructor(@Query(NgValidator) ngValidators: QueryList) { + constructor(@Optional() @Inject(NG_VALIDATORS) validators: Function[]) { super(); - this.ngValidators = ngValidators; + this.validators = validators; } onChanges(c: StringMap) { @@ -66,7 +65,7 @@ export class NgModel extends NgControl { get path(): string[] { return []; } - get validator(): Function { return composeNgValidator(this.ngValidators); } + get validator(): Function { return Validators.compose(this.validators); } viewToModelUpdate(newValue: any): void { this.viewModel = newValue; diff --git a/modules/angular2/src/forms/directives/shared.ts b/modules/angular2/src/forms/directives/shared.ts index 937374de58..6db96ae262 100644 --- a/modules/angular2/src/forms/directives/shared.ts +++ b/modules/angular2/src/forms/directives/shared.ts @@ -3,7 +3,6 @@ import {isBlank, BaseException, looseIdentical} from 'angular2/src/core/facade/l import {ControlContainer} from './control_container'; import {NgControl} from './ng_control'; -import {NgValidator} from './validators'; import {Control} from '../model'; import {Validators} from '../validators'; import {Renderer} from 'angular2/render'; @@ -37,11 +36,6 @@ export function setUpControl(c: Control, dir: NgControl) { dir.valueAccessor.registerOnTouched(() => c.markAsTouched()); } -export function composeNgValidator(ngValidators: QueryList): Function { - if (isBlank(ngValidators)) return Validators.nullValidator; - return Validators.compose(ngValidators.map(v => v.validator)); -} - function _throwError(dir: NgControl, message: string): void { var path = ListWrapper.join(dir.path, " -> "); throw new BaseException(`${message} '${path}'`); diff --git a/modules/angular2/src/forms/directives/validators.ts b/modules/angular2/src/forms/directives/validators.ts index e1e8a71c55..677e223ff5 100644 --- a/modules/angular2/src/forms/directives/validators.ts +++ b/modules/angular2/src/forms/directives/validators.ts @@ -1,19 +1,14 @@ -import {forwardRef, Binding} from 'angular2/di'; +import {forwardRef, OpaqueToken, Binding} from 'angular2/di'; import {CONST_EXPR} from 'angular2/src/core/facade/lang'; import {Directive} from 'angular2/metadata'; -import {Validators} from '../validators'; +import {Validators, NG_VALIDATORS} from '../validators'; -export class NgValidator { - get validator(): Function { throw "Is not implemented"; } -} - -const requiredValidatorBinding = - CONST_EXPR(new Binding(NgValidator, {toAlias: forwardRef(() => NgRequiredValidator)})); +const DEFAULT_VALIDATORS = + CONST_EXPR(new Binding(NG_VALIDATORS, {toValue: Validators.required, multi: true})); @Directive({ selector: '[required][ng-control],[required][ng-form-control],[required][ng-model]', - bindings: [requiredValidatorBinding] + bindings: [DEFAULT_VALIDATORS] }) -export class NgRequiredValidator extends NgValidator { - get validator(): Function { return Validators.required; } +export class DefaultValidators { } diff --git a/modules/angular2/src/forms/validators.ts b/modules/angular2/src/forms/validators.ts index 74eb68b9c2..08a489d005 100644 --- a/modules/angular2/src/forms/validators.ts +++ b/modules/angular2/src/forms/validators.ts @@ -1,8 +1,12 @@ import {isBlank, isPresent} from 'angular2/src/core/facade/lang'; +import {CONST_EXPR} from 'angular2/src/core/facade/lang'; import {ListWrapper, StringMapWrapper} from 'angular2/src/core/facade/collection'; +import {OpaqueToken} from 'angular2/di'; import * as modelModule from './model'; +export const NG_VALIDATORS = CONST_EXPR(new OpaqueToken("NgValidators")); + /** * Provides a set of validators used by form controls. * @@ -20,6 +24,8 @@ export class Validators { static nullValidator(c: any): StringMap { return null; } static compose(validators: Function[]): Function { + if (isBlank(validators)) return Validators.nullValidator; + return function(c: modelModule.Control) { var res = ListWrapper.reduce(validators, (res, validator) => { var errors = validator(c); diff --git a/modules/angular2/test/forms/directives_spec.ts b/modules/angular2/test/forms/directives_spec.ts index 6663d211c3..f7388d34f1 100644 --- a/modules/angular2/test/forms/directives_spec.ts +++ b/modules/angular2/test/forms/directives_spec.ts @@ -14,8 +14,6 @@ import { inject } from 'angular2/test_lib'; -import {QueryList} from 'angular2/angular2'; - import { ControlGroup, Control, @@ -27,7 +25,7 @@ import { NgForm, NgModel, NgFormControl, - NgRequiredValidator + DefaultValidators } from 'angular2/forms'; class DummyControlValueAccessor implements ControlValueAccessor { @@ -51,7 +49,7 @@ export function main() { formModel = new ControlGroup({"login": new Control(null)}); form.form = formModel; - loginControlDir = new NgControlName(form, new QueryList()); + loginControlDir = new NgControlName(form, []); loginControlDir.name = "login"; loginControlDir.valueAccessor = new DummyControlValueAccessor(); }); @@ -85,7 +83,7 @@ export function main() { }); it("should set up validator", () => { - loginControlDir.ngValidators.reset([new NgRequiredValidator()]); + loginControlDir.validators = [Validators.required]; expect(formModel.find(["login"]).valid).toBe(true); @@ -220,7 +218,7 @@ export function main() { var control; beforeEach(() => { - controlDir = new NgFormControl(new QueryList()); + controlDir = new NgFormControl([]); controlDir.valueAccessor = new DummyControlValueAccessor(); control = new Control(null); @@ -239,7 +237,7 @@ export function main() { }); it("should set up validator", () => { - controlDir.ngValidators.reset([new NgRequiredValidator()]); + controlDir.validators = [Validators.required]; expect(control.valid).toBe(true); @@ -254,7 +252,7 @@ export function main() { var ngModel; beforeEach(() => { - ngModel = new NgModel(new QueryList()); + ngModel = new NgModel([]); ngModel.valueAccessor = new DummyControlValueAccessor(); }); @@ -271,7 +269,7 @@ export function main() { }); it("should set up validator", () => { - ngModel.ngValidators.reset([new NgRequiredValidator()]); + ngModel.validators = [Validators.required]; expect(ngModel.control.valid).toBe(true); @@ -291,7 +289,7 @@ export function main() { var parent = new NgFormModel(); parent.form = new ControlGroup({"name": formModel}); - controlNameDir = new NgControlName(parent, new QueryList()); + controlNameDir = new NgControlName(parent, []); controlNameDir.name = "name"; }); diff --git a/modules/angular2/test/forms/validators_spec.ts b/modules/angular2/test/forms/validators_spec.ts index 8fbb807691..f4d72f607a 100644 --- a/modules/angular2/test/forms/validators_spec.ts +++ b/modules/angular2/test/forms/validators_spec.ts @@ -33,6 +33,9 @@ export function main() { }); describe("compose", () => { + it("should return a null validator when given null", + () => { expect(Validators.compose(null)).toBe(Validators.nullValidator); }); + it("should collect errors from all the validators", () => { var c = Validators.compose([validator("a", true), validator("b", true)]); expect(c(new Control(""))).toEqual({"a": true, "b": true});