import { PromiseWrapper, ObservableWrapper, EventEmitter, PromiseCompleter } from 'angular2/src/facade/async'; import {StringMapWrapper, List, ListWrapper} from 'angular2/src/facade/collection'; import {isPresent, isBlank, CONST_EXPR} from 'angular2/src/facade/lang'; import {Directive} from 'angular2/annotations'; import {forwardRef, Binding} from 'angular2/di'; import {NgControl} from './ng_control'; import {Form} from './form_interface'; import {NgControlGroup} from './ng_control_group'; import {ControlContainer} from './control_container'; import {AbstractControl, ControlGroup, Control} from '../model'; import {setUpControl} from './shared'; const formDirectiveBinding = CONST_EXPR(new Binding(ControlContainer, {toAlias: forwardRef(() => NgForm)})); /** * Creates and binds a form object to a DOM element. * * # Example * * ``` * @Component({selector: "signup-comp"}) * @View({ * directives: [formDirectives], * template: ` *
*
* Login * Password *
*
Credentials are invalid
* *
* Name *
* *
* `}) * class SignupComp { * onSignUp(value) { * // value === {personal: {name: 'some name'}, * // credentials: {login: 'some login', password: 'some password'}} * } * } * * ``` */ @Directive({ selector: 'form:not([ng-no-form]):not([ng-form-model]),ng-form,[ng-form]', bindings: [formDirectiveBinding], host: { '(submit)': 'onSubmit()', }, events: ['ngSubmit'], exportAs: 'form' }) export class NgForm extends ControlContainer implements Form { form: ControlGroup; ngSubmit = new EventEmitter(); constructor() { super(); this.form = new ControlGroup({}); } get formDirective(): Form { return this; } get control(): ControlGroup { return this.form; } get path(): List { return []; } get controls(): StringMap { return this.form.controls; } addControl(dir: NgControl): void { this._later(_ => { var container = this._findContainer(dir.path); var c = new Control(); setUpControl(c, dir); container.addControl(dir.name, c); c.updateValidity(); }); } getControl(dir: NgControl): Control { return this.form.find(dir.path); } removeControl(dir: NgControl): void { this._later(_ => { var container = this._findContainer(dir.path); if (isPresent(container)) { container.removeControl(dir.name); container.updateValidity(); } }); } addControlGroup(dir: NgControlGroup): void { this._later(_ => { var container = this._findContainer(dir.path); var c = new ControlGroup({}); container.addControl(dir.name, c); c.updateValidity(); }); } removeControlGroup(dir: NgControlGroup): void { this._later(_ => { var container = this._findContainer(dir.path); if (isPresent(container)) { container.removeControl(dir.name); container.updateValidity(); } }); } getControlGroup(dir: NgControlGroup): ControlGroup { return this.form.find(dir.path); } updateModel(dir: NgControl, value: any): void { this._later(_ => { var c = this.form.find(dir.path); c.updateValue(value); }); } onSubmit(): boolean { ObservableWrapper.callNext(this.ngSubmit, null); return false; } _findContainer(path: List): ControlGroup { ListWrapper.removeLast(path); return ListWrapper.isEmpty(path) ? this.form : this.form.find(path); } _later(fn) { var c: PromiseCompleter = PromiseWrapper.completer(); PromiseWrapper.then(c.promise, fn, (_) => {}); c.resolve(null); } }