diff --git a/modules/angular2/forms.js b/modules/angular2/forms.js index 5bbf9237bf..c6b0c5d325 100644 --- a/modules/angular2/forms.js +++ b/modules/angular2/forms.js @@ -1,4 +1,3 @@ export * from './src/forms/model'; export * from './src/forms/directives'; -export * from './src/forms/validators'; -export * from './src/forms/validator_directives'; +export * from './src/forms/validators'; \ No newline at end of file diff --git a/modules/angular2/src/forms/directives.js b/modules/angular2/src/forms/directives.js index fac04a8261..9ca80e38a4 100644 --- a/modules/angular2/src/forms/directives.js +++ b/modules/angular2/src/forms/directives.js @@ -5,11 +5,6 @@ import {StringMapWrapper, ListWrapper} from 'angular2/src/facade/collection'; import {ControlGroup, Control} from './model'; import * as validators from './validators'; -class ControlGroupDirectiveBase { - addDirective(directive):void {} - findControl(name:string):Control { return null; } -} - @CONST() export class ControlValueAccessor { readValue(el){} @@ -60,9 +55,16 @@ function controlValueAccessorFor(controlType:string):ControlValueAccessor { } } - -export class ControlDirectiveBase { - _groupDecorator:ControlGroupDirectiveBase; +@Decorator({ + lifecycle: [onChange], + selector: '[control]', + bind: { + 'controlName' : 'control', + 'type' : 'type' + } +}) +export class ControlDirective { + _groupDecorator:ControlGroupDirective; _el:NgElement; controlName:string; @@ -71,12 +73,18 @@ export class ControlDirectiveBase { validator:Function; - constructor(groupDecorator, el:NgElement) { + constructor(@Ancestor() groupDecorator:ControlGroupDirective, el:NgElement) { this._groupDecorator = groupDecorator; this._el = el; this.validator = validators.nullValidator; } + // TODO: vsavkin this should be moved into the constructor once static bindings + // are implemented + onChange(_) { + this._initialize(); + } + _initialize() { this._groupDecorator.addDirective(this); @@ -105,51 +113,15 @@ export class ControlDirectiveBase { } } -@Decorator({ - lifecycle: [onChange], - selector: '[control-name]', - bind: { - 'controlName' : 'control-name', - 'type' : 'type' - } -}) -export class ControlNameDirective extends ControlDirectiveBase { - constructor(@Ancestor() groupDecorator:ControlGroupDirective, el:NgElement) { - super(groupDecorator, el); - } - - onChange(_) { - this._initialize(); - } -} - -@Decorator({ - lifecycle: [onChange], - selector: '[control]', - bind: { - 'controlName' : 'control', - 'type' : 'type' - } -}) -export class ControlDirective extends ControlDirectiveBase { - constructor(@Ancestor() groupDecorator:NewControlGroupDirective, el:NgElement) { - super(groupDecorator, el); - } - - onChange(_) { - this._initialize(); - } -} - @Decorator({ selector: '[control-group]', bind: { 'controlGroup' : 'control-group' } }) -export class ControlGroupDirective extends ControlGroupDirectiveBase { +export class ControlGroupDirective { _controlGroup:ControlGroup; - _directives:List; + _directives:List; constructor() { super(); @@ -161,71 +133,15 @@ export class ControlGroupDirective extends ControlGroupDirectiveBase { ListWrapper.forEach(this._directives, (cd) => cd._updateDomValue()); } - addDirective(c:ControlNameDirective) { - ListWrapper.push(this._directives, c); - } - - findControl(name:string):Control { - return this._controlGroup.controls[name]; - } -} - -@Component({ - selector: '[new-control-group]', - bind: { - 'initData' : 'new-control-group' - } -}) -@Template({inline: ''}) -export class NewControlGroupDirective extends ControlGroupDirectiveBase { - _initData:any; - _controlGroup:ControlGroup; - _directives:List; - - constructor() { - super(); - this._directives = ListWrapper.create(); - } - - set initData(value) { - this._initData = value; - } - addDirective(c:ControlDirective) { ListWrapper.push(this._directives, c); - this._controlGroup = null; } findControl(name:string):Control { - if (isBlank(this._controlGroup)) { - this._controlGroup = this._createControlGroup(); - } return this._controlGroup.controls[name]; } - - _createControlGroup():ControlGroup { - var controls = ListWrapper.reduce(this._directives, (memo, cd) => { - var initControlValue = this._initData[cd.controlName]; - memo[cd.controlName] = new Control(initControlValue); - return memo; - }, {}); - return new ControlGroup(controls); - } - - get value() { - return this._controlGroup.value; - } - - get errors() { - return this._controlGroup.errors; - } - - get valid() { - return this._controlGroup.valid; - } } export var FormDirectives = [ - ControlGroupDirective, ControlNameDirective, - ControlDirective, NewControlGroupDirective + ControlGroupDirective, ControlDirective ]; diff --git a/modules/angular2/test/forms/integration_spec.js b/modules/angular2/test/forms/integration_spec.js index a6a26b5042..b77c4ddc62 100644 --- a/modules/angular2/test/forms/integration_spec.js +++ b/modules/angular2/test/forms/integration_spec.js @@ -15,10 +15,10 @@ import {MockTemplateResolver} from 'angular2/src/mock/template_resolver_mock'; import {Injector} from 'angular2/di'; import {Component, Decorator, Template} from 'angular2/core'; -import {ControlGroupDirective, ControlNameDirective, - ControlDirective, NewControlGroupDirective, - Control, ControlGroup, ControlValueAccessor, - RequiredValidatorDirective} from 'angular2/forms'; +import {ControlGroupDirective, ControlDirective, Control, ControlGroup, + ControlValueAccessor, RequiredValidatorDirective} from 'angular2/forms'; + +import * as validators from 'angular2/src/forms/validators'; export function main() { function detectChanges(view) { @@ -42,8 +42,7 @@ export function main() { tplResolver.setTemplate(componentType, new Template({ inline: template, - directives: [ControlGroupDirective, ControlNameDirective, ControlDirective, - NewControlGroupDirective, WrappedValue] + directives: [ControlGroupDirective, ControlDirective, WrappedValue] })); compiler.compile(componentType).then((pv) => { @@ -61,7 +60,7 @@ export function main() { })); var t = `
- +
`; compile(MyComp, t, ctx, (view) => { @@ -78,7 +77,7 @@ export function main() { var ctx = new MyComp(form); var t = `
- +
`; compile(MyComp, t, ctx, (view) => { @@ -99,7 +98,7 @@ export function main() { var ctx = new MyComp(form); var t = `
- +
`; compile(MyComp, t, ctx, (view) => { @@ -121,7 +120,7 @@ export function main() { }), "one"); var t = `
- +
`; compile(MyComp, t, ctx, (view) => { @@ -141,7 +140,7 @@ export function main() { var ctx = new MyComp(new ControlGroup({"checkbox": new Control(true)})); var t = `
- +
`; compile(MyComp, t, ctx, (view) => { @@ -160,7 +159,7 @@ export function main() { var ctx = new MyComp(new ControlGroup({"name": new Control("aa")})); var t = `
- +
`; compile(MyComp, t, ctx, (view) => { @@ -176,48 +175,37 @@ export function main() { }); }); - describe("declarative forms", () => { - it("should initialize dom elements", (done) => { - var t = `
- - -
`; + describe("validations", () => { + it("should use validators defined in html",(done) => { + var form = new ControlGroup({"login": new Control("aa")}); + var ctx = new MyComp(form); - compile(MyComp, t, new MyComp(), (view) => { - var loginInput = queryView(view, "#login") - expect(loginInput.value).toEqual("loginValue"); + var t = `
+ +
`; - var passInput = queryView(view, "#password") - expect(passInput.value).toEqual("passValue"); + compile(MyComp, t, ctx, (view) => { + expect(form.valid).toEqual(true); - done(); - }); - }); + var input = queryView(view, "input"); - it("should update the control group values on DOM change", (done) => { - var t = `
- -
`; - - compile(MyComp, t, new MyComp(), (view) => { - var input = queryView(view, "input") - - input.value = "updatedValue"; + input.value = ""; dispatchEvent(input, "change"); - var form = view.contextWithLocals.get("form"); - expect(form.value).toEqual({'login': 'updatedValue'}); + expect(form.valid).toEqual(false); done(); }); }); - it("should support validators",(done) => { - var t = `
- -
`; + it("should use validators defined in the model",(done) => { + var form = new ControlGroup({"login": new Control("aa", validators.required)}); + var ctx = new MyComp(form); - compile(MyComp, t, new MyComp(), (view) => { - var form = view.contextWithLocals.get("form"); + var t = `
+ +
`; + + compile(MyComp, t, ctx, (view) => { expect(form.valid).toEqual(true); var input = queryView(view, "input"); @@ -236,12 +224,6 @@ export function main() { @Component({ selector: "my-comp" }) -@Template({ - inline: "", - directives: [ControlGroupDirective, ControlNameDirective, - ControlDirective, NewControlGroupDirective, RequiredValidatorDirective, - WrappedValue] -}) class MyComp { form:ControlGroup; name:string; @@ -266,7 +248,7 @@ class WrappedValueAccessor extends ControlValueAccessor { selector:'[wrapped-value]' }) class WrappedValue { - constructor(cd:ControlNameDirective) { + constructor(cd:ControlDirective) { cd.valueAccessor = new WrappedValueAccessor(); } }