parent
							
								
									73351ac00f
								
							
						
					
					
						commit
						d6cda15879
					
				| @ -40,7 +40,7 @@ export class CheckboxControlValueAccessor implements ControlValueAccessor { | |||||||
|     cd.valueAccessor = this; |     cd.valueAccessor = this; | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   writeValue(value: any) { setProperty(this._renderer, this._elementRef, "checked", value); } |   writeValue(value: any): void { setProperty(this._renderer, this._elementRef, "checked", value); } | ||||||
| 
 | 
 | ||||||
|   get ngClassUntouched(): boolean { |   get ngClassUntouched(): boolean { | ||||||
|     return isPresent(this._cd.control) ? this._cd.control.untouched : false; |     return isPresent(this._cd.control) ? this._cd.control.untouched : false; | ||||||
|  | |||||||
| @ -2,7 +2,7 @@ import {Form} from './form_interface'; | |||||||
| import {AbstractControlDirective} from './abstract_control_directive'; | import {AbstractControlDirective} from './abstract_control_directive'; | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
|  * A directive that contains a group of [NgControl]. |  * A directive that contains multiple {@link NgControl}. | ||||||
|  * |  * | ||||||
|  * Only used by the forms module. |  * Only used by the forms module. | ||||||
|  */ |  */ | ||||||
|  | |||||||
| @ -41,9 +41,7 @@ export class DefaultValueAccessor implements ControlValueAccessor { | |||||||
|     cd.valueAccessor = this; |     cd.valueAccessor = this; | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   writeValue(value: any) { |   writeValue(value: any): void { | ||||||
|     // both this.value and setProperty are required at the moment
 |  | ||||||
|     // remove when a proper imperative API is provided
 |  | ||||||
|     var normalizedValue = isBlank(value) ? '' : value; |     var normalizedValue = isBlank(value) ? '' : value; | ||||||
|     setProperty(this._renderer, this._elementRef, 'value', normalizedValue); |     setProperty(this._renderer, this._elementRef, 'value', normalizedValue); | ||||||
|   } |   } | ||||||
|  | |||||||
| @ -42,7 +42,8 @@ const controlGroupBinding = | |||||||
|  *      `})
 |  *      `})
 | ||||||
|  * class SignupComp { |  * class SignupComp { | ||||||
|  *  onSignUp(value) { |  *  onSignUp(value) { | ||||||
|  *    // value === {personal: {name: 'some name'},
 |  *    // value === {
 | ||||||
|  |  *    //  personal: {name: 'some name'},
 | ||||||
|  *    //  credentials: {login: 'some login', password: 'some password'}}
 |  *    //  credentials: {login: 'some login', password: 'some password'}}
 | ||||||
|  *  } |  *  } | ||||||
|  * } |  * } | ||||||
| @ -63,9 +64,9 @@ export class NgControlGroup extends ControlContainer implements OnInit, | |||||||
|     this._parent = _parent; |     this._parent = _parent; | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   onInit() { this.formDirective.addControlGroup(this); } |   onInit(): void { this.formDirective.addControlGroup(this); } | ||||||
| 
 | 
 | ||||||
|   onDestroy() { this.formDirective.removeControlGroup(this); } |   onDestroy(): void { this.formDirective.removeControlGroup(this); } | ||||||
| 
 | 
 | ||||||
|   get control(): ControlGroup { return this.formDirective.getControlGroup(this); } |   get control(): ControlGroup { return this.formDirective.getControlGroup(this); } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -24,24 +24,23 @@ const controlNameBinding = | |||||||
|  * |  * | ||||||
|  * In this example, we create the login and password controls. |  * In this example, we create the login and password controls. | ||||||
|  * We can work with each control separately: check its validity, get its value, listen to its |  * We can work with each control separately: check its validity, get its value, listen to its | ||||||
|  changes. |  * changes. | ||||||
|  * |  * | ||||||
|  *  ``` |  *  ``` | ||||||
|  * @Component({selector: "login-comp"}) |  * @Component({selector: "login-comp"}) | ||||||
|  * @View({ |  * @View({ | ||||||
|  *      directives: [FORM_DIRECTIVES], |  *      directives: [FORM_DIRECTIVES], | ||||||
|  *      template: ` |  *      template: ` | ||||||
|  *              <form #f="form" (submit)='onLogIn(f.value)'> |  *        <form #f="form" (submit)='onLogIn(f.value)'> | ||||||
|  *                Login <input type='text' ng-control='login' #l="form"> |  *          Login <input type='text' ng-control='login' #l="form"> | ||||||
|  *                <div *ng-if="!l.valid">Login is invalid</div> |  *          <div *ng-if="!l.valid">Login is invalid</div> | ||||||
|  * |  * | ||||||
|  *                Password <input type='password' ng-control='password'> |  *          Password <input type='password' ng-control='password'> | ||||||
| 
 |  *          <button type='submit'>Log in!</button> | ||||||
|  *                <button type='submit'>Log in!</button> |  *        </form> | ||||||
|  *              </form> |  | ||||||
|  *      `})
 |  *      `})
 | ||||||
|  * class LoginComp { |  * class LoginComp { | ||||||
|  *  onLogIn(value) { |  *  onLogIn(value): void { | ||||||
|  *    // value === {login: 'some login', password: 'some password'}
 |  *    // value === {login: 'some login', password: 'some password'}
 | ||||||
|  *  } |  *  } | ||||||
|  * } |  * } | ||||||
| @ -54,17 +53,17 @@ const controlNameBinding = | |||||||
|  * @View({ |  * @View({ | ||||||
|  *      directives: [FORM_DIRECTIVES], |  *      directives: [FORM_DIRECTIVES], | ||||||
|  *      template: ` |  *      template: ` | ||||||
|  *              <form (submit)='onLogIn()'> |  *        <form (submit)='onLogIn()'> | ||||||
|  *                Login <input type='text' ng-control='login' [(ng-model)]="credentials.login"> |  *          Login <input type='text' ng-control='login' [(ng-model)]="credentials.login"> | ||||||
|  *                Password <input type='password' ng-control='password' |  *          Password <input type='password' ng-control='password' | ||||||
|  [(ng-model)]="credentials.password"> |  *                          [(ng-model)]="credentials.password"> | ||||||
|  *                <button type='submit'>Log in!</button> |  *          <button type='submit'>Log in!</button> | ||||||
|  *              </form> |  *        </form> | ||||||
|  *      `})
 |  *      `})
 | ||||||
|  * class LoginComp { |  * class LoginComp { | ||||||
|  *  credentials: {login:string, password:string}; |  *  credentials: {login:string, password:string}; | ||||||
|  * |  * | ||||||
|  *  onLogIn() { |  *  onLogIn(): void { | ||||||
|  *    // this.credentials.login === "some login"
 |  *    // this.credentials.login === "some login"
 | ||||||
|  *    // this.credentials.password === "some password"
 |  *    // this.credentials.password === "some password"
 | ||||||
|  *  } |  *  } | ||||||
| @ -94,18 +93,18 @@ export class NgControlName extends NgControl implements OnChanges, | |||||||
|     this.validators = validators; |     this.validators = validators; | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   onChanges(c: StringMap<string, any>) { |   onChanges(changes: StringMap<string, any>) { | ||||||
|     if (!this._added) { |     if (!this._added) { | ||||||
|       this.formDirective.addControl(this); |       this.formDirective.addControl(this); | ||||||
|       this._added = true; |       this._added = true; | ||||||
|     } |     } | ||||||
|     if (isPropertyUpdated(c, this.viewModel)) { |     if (isPropertyUpdated(changes, this.viewModel)) { | ||||||
|       this.viewModel = this.model; |       this.viewModel = this.model; | ||||||
|       this.formDirective.updateModel(this, this.model); |       this.formDirective.updateModel(this, this.model); | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   onDestroy() { this.formDirective.removeControl(this); } |   onDestroy(): void { this.formDirective.removeControl(this); } | ||||||
| 
 | 
 | ||||||
|   viewToModelUpdate(newValue: any): void { |   viewToModelUpdate(newValue: any): void { | ||||||
|     this.viewModel = newValue; |     this.viewModel = newValue; | ||||||
|  | |||||||
| @ -42,8 +42,9 @@ const formDirectiveBinding = | |||||||
|  *              </form> |  *              </form> | ||||||
|  *      `})
 |  *      `})
 | ||||||
|  * class SignupComp { |  * class SignupComp { | ||||||
|  *  onSignUp(value) { |  *  onSignUp(value): void { | ||||||
|  *    // value === {personal: {name: 'some name'},
 |  *    // value === {
 | ||||||
|  |  *    //  personal: {name: 'some name'},
 | ||||||
|  *    //  credentials: {login: 'some login', password: 'some password'}}
 |  *    //  credentials: {login: 'some login', password: 'some password'}}
 | ||||||
|  *  } |  *  } | ||||||
|  * } |  * } | ||||||
| @ -60,14 +61,9 @@ const formDirectiveBinding = | |||||||
|   exportAs: 'form' |   exportAs: 'form' | ||||||
| }) | }) | ||||||
| export class NgForm extends ControlContainer implements Form { | export class NgForm extends ControlContainer implements Form { | ||||||
|   form: ControlGroup; |   form: ControlGroup = new ControlGroup({}); | ||||||
|   ngSubmit = new EventEmitter(); |   ngSubmit = new EventEmitter(); | ||||||
| 
 | 
 | ||||||
|   constructor() { |  | ||||||
|     super(); |  | ||||||
|     this.form = new ControlGroup({}); |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   get formDirective(): Form { return this; } |   get formDirective(): Form { return this; } | ||||||
| 
 | 
 | ||||||
|   get control(): ControlGroup { return this.form; } |   get control(): ControlGroup { return this.form; } | ||||||
| @ -79,10 +75,10 @@ export class NgForm extends ControlContainer implements Form { | |||||||
|   addControl(dir: NgControl): void { |   addControl(dir: NgControl): void { | ||||||
|     this._later(_ => { |     this._later(_ => { | ||||||
|       var container = this._findContainer(dir.path); |       var container = this._findContainer(dir.path); | ||||||
|       var c = new Control(); |       var ctrl = new Control(); | ||||||
|       setUpControl(c, dir); |       setUpControl(ctrl, dir); | ||||||
|       container.addControl(dir.name, c); |       container.addControl(dir.name, ctrl); | ||||||
|       c.updateValidity(); |       ctrl.updateValidity(); | ||||||
|     }); |     }); | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
| @ -101,9 +97,9 @@ export class NgForm extends ControlContainer implements Form { | |||||||
|   addControlGroup(dir: NgControlGroup): void { |   addControlGroup(dir: NgControlGroup): void { | ||||||
|     this._later(_ => { |     this._later(_ => { | ||||||
|       var container = this._findContainer(dir.path); |       var container = this._findContainer(dir.path); | ||||||
|       var c = new ControlGroup({}); |       var group = new ControlGroup({}); | ||||||
|       container.addControl(dir.name, c); |       container.addControl(dir.name, group); | ||||||
|       c.updateValidity(); |       group.updateValidity(); | ||||||
|     }); |     }); | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
| @ -123,8 +119,8 @@ export class NgForm extends ControlContainer implements Form { | |||||||
| 
 | 
 | ||||||
|   updateModel(dir: NgControl, value: any): void { |   updateModel(dir: NgControl, value: any): void { | ||||||
|     this._later(_ => { |     this._later(_ => { | ||||||
|       var c = <Control>this.form.find(dir.path); |       var ctrl = <Control>this.form.find(dir.path); | ||||||
|       c.updateValue(value); |       ctrl.updateValue(value); | ||||||
|     }); |     }); | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
| @ -138,9 +134,5 @@ export class NgForm extends ControlContainer implements Form { | |||||||
|     return ListWrapper.isEmpty(path) ? this.form : <ControlGroup>this.form.find(path); |     return ListWrapper.isEmpty(path) ? this.form : <ControlGroup>this.form.find(path); | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   _later(fn) { |   _later(fn): void { PromiseWrapper.then(PromiseWrapper.resolve(null), fn, (_) => {}); } | ||||||
|     var c: PromiseCompleter<any> = PromiseWrapper.completer(); |  | ||||||
|     PromiseWrapper.then(c.promise, fn, (_) => {}); |  | ||||||
|     c.resolve(null); |  | ||||||
|   } |  | ||||||
| } | } | ||||||
|  | |||||||
| @ -17,10 +17,8 @@ const formControlBinding = | |||||||
|  * # Example |  * # Example | ||||||
|  * |  * | ||||||
|  * In this example, we bind the control to an input element. When the value of the input element |  * In this example, we bind the control to an input element. When the value of the input element | ||||||
|  * changes, the value of |  * changes, the value of the control will reflect that change. Likewise, if the value of the | ||||||
|  * the control will reflect that change. Likewise, if the value of the control changes, the input |  * control changes, the input element reflects that change. | ||||||
|  * element reflects that |  | ||||||
|  * change. |  | ||||||
|  * |  * | ||||||
|  *  ``` |  *  ``` | ||||||
|  * @Component({selector: "login-comp"}) |  * @Component({selector: "login-comp"}) | ||||||
| @ -29,16 +27,12 @@ const formControlBinding = | |||||||
|  *      template: "<input type='text' [ng-form-control]='loginControl'>" |  *      template: "<input type='text' [ng-form-control]='loginControl'>" | ||||||
|  *      }) |  *      }) | ||||||
|  * class LoginComp { |  * class LoginComp { | ||||||
|  *  loginControl:Control; |  *  loginControl: Control = new Control('');; | ||||||
|  * |  | ||||||
|  *  constructor() { |  | ||||||
|  *    this.loginControl = new Control(''); |  | ||||||
|  *  } |  | ||||||
|  * } |  * } | ||||||
|  * |  * | ||||||
|  *  ``` |  *  ``` | ||||||
|  * |  * | ||||||
|  * We can also use ng-model to bind a domain model to the form. |  * We can also use `ng-model` to bind a domain model to the form. | ||||||
|  * |  * | ||||||
|  *  ``` |  *  ``` | ||||||
|  * @Component({selector: "login-comp"}) |  * @Component({selector: "login-comp"}) | ||||||
| @ -47,12 +41,8 @@ const formControlBinding = | |||||||
|  *      template: "<input type='text' [ng-form-control]='loginControl' [(ng-model)]='login'>" |  *      template: "<input type='text' [ng-form-control]='loginControl' [(ng-model)]='login'>" | ||||||
|  *      }) |  *      }) | ||||||
|  * class LoginComp { |  * class LoginComp { | ||||||
|  *  loginControl:Control; |  *  loginControl: Control = new Control(''); | ||||||
|  *  login:string; |  *  login:string; | ||||||
|  * |  | ||||||
|  *  constructor() { |  | ||||||
|  *    this.loginControl = new Control(''); |  | ||||||
|  *  } |  | ||||||
|  * } |  * } | ||||||
|  *  ``` |  *  ``` | ||||||
|  */ |  */ | ||||||
| @ -76,13 +66,13 @@ export class NgFormControl extends NgControl implements OnChanges { | |||||||
|     this.validators = validators; |     this.validators = validators; | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   onChanges(c: StringMap<string, any>) { |   onChanges(changes: StringMap<string, any>): void { | ||||||
|     if (!this._added) { |     if (!this._added) { | ||||||
|       setUpControl(this.form, this); |       setUpControl(this.form, this); | ||||||
|       this.form.updateValidity(); |       this.form.updateValidity(); | ||||||
|       this._added = true; |       this._added = true; | ||||||
|     } |     } | ||||||
|     if (isPropertyUpdated(c, this.viewModel)) { |     if (isPropertyUpdated(changes, this.viewModel)) { | ||||||
|       this.form.updateValue(this.model); |       this.form.updateValue(this.model); | ||||||
|       this.viewModel = this.model; |       this.viewModel = this.model; | ||||||
|     } |     } | ||||||
|  | |||||||
| @ -21,21 +21,21 @@ const formDirectiveBinding = | |||||||
|  * # Example |  * # Example | ||||||
|  * |  * | ||||||
|  * In this example, we bind the control group to the form element, and we bind the login and |  * In this example, we bind the control group to the form element, and we bind the login and | ||||||
|  * password controls to the |  * password controls to the login and password elements. | ||||||
|  * login and password elements. |  | ||||||
|  * |  * | ||||||
|  *  ``` |  *  ``` | ||||||
|  * @Component({selector: "login-comp"}) |  * @Component({selector: "login-comp"}) | ||||||
|  * @View({ |  * @View({ | ||||||
|  *      directives: [FORM_DIRECTIVES], |  *      directives: [FORM_DIRECTIVES], | ||||||
|  *      template: "<form [ng-form-model]='loginForm'>" + |  *      template: ` | ||||||
|  *              "Login <input type='text' ng-control='login'>" + |  *        <form [ng-form-model]='loginForm'> | ||||||
|  *              "Password <input type='password' ng-control='password'>" + |  *          Login <input type='text' ng-control='login'> | ||||||
|  *              "<button (click)="onLogin()">Login</button>" + |  *          Password <input type='password' ng-control='password'> | ||||||
|  *              "</form>" |  *          <button (click)="onLogin()">Login</button> | ||||||
|  |  *        </form>` | ||||||
|  *      }) |  *      }) | ||||||
|  * class LoginComp { |  * class LoginComp { | ||||||
|  *  loginForm:ControlGroup; |  *  loginForm: ControlGroup; | ||||||
|  * |  * | ||||||
|  *  constructor() { |  *  constructor() { | ||||||
|  *    this.loginForm = new ControlGroup({ |  *    this.loginForm = new ControlGroup({ | ||||||
| @ -44,7 +44,7 @@ const formDirectiveBinding = | |||||||
|  *    }); |  *    }); | ||||||
|  *  } |  *  } | ||||||
|  * |  * | ||||||
|  *  onLogin() { |  *  onLogin(): void { | ||||||
|  *    // this.loginForm.value
 |  *    // this.loginForm.value
 | ||||||
|  *  } |  *  } | ||||||
|  * } |  * } | ||||||
| @ -57,15 +57,17 @@ const formDirectiveBinding = | |||||||
|  * @Component({selector: "login-comp"}) |  * @Component({selector: "login-comp"}) | ||||||
|  * @View({ |  * @View({ | ||||||
|  *      directives: [FORM_DIRECTIVES], |  *      directives: [FORM_DIRECTIVES], | ||||||
|  *      template: "<form [ng-form-model]='loginForm'>" + |  *      template: ` | ||||||
|  *              "Login <input type='text' ng-control='login' [(ng-model)]='login'>" + |  *        <form [ng-form-model]='loginForm'> | ||||||
|  *              "Password <input type='password' ng-control='password' [(ng-model)]='password'>" + |  *          Login <input type='text' ng-control='login' [(ng-model)]='credentials.login'> | ||||||
|  *              "<button (click)="onLogin()">Login</button>" + |  *          Password <input type='password' ng-control='password' | ||||||
|  *              "</form>" |  *                          [(ng-model)]='credentials.password'> | ||||||
|  |  *          <button (click)="onLogin()">Login</button> | ||||||
|  |  *        </form>` | ||||||
|  *      }) |  *      }) | ||||||
|  * class LoginComp { |  * class LoginComp { | ||||||
|  *  credentials:{login:string, password:string} |  *  credentials: {login: string, password: string}; | ||||||
|  *  loginForm:ControlGroup; |  *  loginForm: ControlGroup; | ||||||
|  * |  * | ||||||
|  *  constructor() { |  *  constructor() { | ||||||
|  *    this.loginForm = new ControlGroup({ |  *    this.loginForm = new ControlGroup({ | ||||||
| @ -74,7 +76,7 @@ const formDirectiveBinding = | |||||||
|  *    }); |  *    }); | ||||||
|  *  } |  *  } | ||||||
|  * |  * | ||||||
|  *  onLogin() { |  *  onLogin(): void { | ||||||
|  *    // this.credentials.login === 'some login'
 |  *    // this.credentials.login === 'some login'
 | ||||||
|  *    // this.credentials.password === 'some password'
 |  *    // this.credentials.password === 'some password'
 | ||||||
|  *  } |  *  } | ||||||
| @ -85,9 +87,7 @@ const formDirectiveBinding = | |||||||
|   selector: '[ng-form-model]', |   selector: '[ng-form-model]', | ||||||
|   bindings: [formDirectiveBinding], |   bindings: [formDirectiveBinding], | ||||||
|   properties: ['form: ng-form-model'], |   properties: ['form: ng-form-model'], | ||||||
|   host: { |   host: {'(submit)': 'onSubmit()'}, | ||||||
|     '(submit)': 'onSubmit()', |  | ||||||
|   }, |  | ||||||
|   events: ['ngSubmit'], |   events: ['ngSubmit'], | ||||||
|   exportAs: 'form' |   exportAs: 'form' | ||||||
| }) | }) | ||||||
| @ -97,7 +97,7 @@ export class NgFormModel extends ControlContainer implements Form, | |||||||
|   directives: NgControl[] = []; |   directives: NgControl[] = []; | ||||||
|   ngSubmit = new EventEmitter(); |   ngSubmit = new EventEmitter(); | ||||||
| 
 | 
 | ||||||
|   onChanges(_) { this._updateDomValue(); } |   onChanges(_): void { this._updateDomValue(); } | ||||||
| 
 | 
 | ||||||
|   get formDirective(): Form { return this; } |   get formDirective(): Form { return this; } | ||||||
| 
 | 
 | ||||||
| @ -106,9 +106,9 @@ export class NgFormModel extends ControlContainer implements Form, | |||||||
|   get path(): string[] { return []; } |   get path(): string[] { return []; } | ||||||
| 
 | 
 | ||||||
|   addControl(dir: NgControl): void { |   addControl(dir: NgControl): void { | ||||||
|     var c: any = this.form.find(dir.path); |     var ctrl: any = this.form.find(dir.path); | ||||||
|     setUpControl(c, dir); |     setUpControl(ctrl, dir); | ||||||
|     c.updateValidity(); |     ctrl.updateValidity(); | ||||||
|     this.directives.push(dir); |     this.directives.push(dir); | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
| @ -125,8 +125,8 @@ export class NgFormModel extends ControlContainer implements Form, | |||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   updateModel(dir: NgControl, value: any): void { |   updateModel(dir: NgControl, value: any): void { | ||||||
|     var c  = <Control>this.form.find(dir.path); |     var ctrl  = <Control>this.form.find(dir.path); | ||||||
|     c.updateValue(value); |     ctrl.updateValue(value); | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   onSubmit(): boolean { |   onSubmit(): boolean { | ||||||
| @ -136,8 +136,8 @@ export class NgFormModel extends ControlContainer implements Form, | |||||||
| 
 | 
 | ||||||
|   _updateDomValue() { |   _updateDomValue() { | ||||||
|     ListWrapper.forEach(this.directives, dir => { |     ListWrapper.forEach(this.directives, dir => { | ||||||
|       var c: any = this.form.find(dir.path); |       var ctrl: any = this.form.find(dir.path); | ||||||
|       dir.valueAccessor.writeValue(c.value); |       dir.valueAccessor.writeValue(ctrl.value); | ||||||
|     }); |     }); | ||||||
|   } |   } | ||||||
| } | } | ||||||
|  | |||||||
| @ -20,9 +20,8 @@ const formControlBinding = CONST_EXPR(new Binding(NgControl, {toAlias: forwardRe | |||||||
|  * @Component({selector: "search-comp"}) |  * @Component({selector: "search-comp"}) | ||||||
|  * @View({ |  * @View({ | ||||||
|  *      directives: [FORM_DIRECTIVES], |  *      directives: [FORM_DIRECTIVES], | ||||||
|  *      template: ` |  *      template: `<input type='text' [(ng-model)]="searchQuery">` | ||||||
|               <input type='text' [(ng-model)]="searchQuery"> |  *      }) | ||||||
|  *      `})
 |  | ||||||
|  * class SearchComp { |  * class SearchComp { | ||||||
|  *  searchQuery: string; |  *  searchQuery: string; | ||||||
|  * } |  * } | ||||||
| @ -48,14 +47,14 @@ export class NgModel extends NgControl implements OnChanges { | |||||||
|     this.validators = validators; |     this.validators = validators; | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   onChanges(c: StringMap<string, any>) { |   onChanges(changes: StringMap<string, any>) { | ||||||
|     if (!this._added) { |     if (!this._added) { | ||||||
|       setUpControl(this._control, this); |       setUpControl(this._control, this); | ||||||
|       this._control.updateValidity(); |       this._control.updateValidity(); | ||||||
|       this._added = true; |       this._added = true; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     if (isPropertyUpdated(c, this.viewModel)) { |     if (isPropertyUpdated(changes, this.viewModel)) { | ||||||
|       this._control.updateValue(this.model); |       this._control.updateValue(this.model); | ||||||
|       this.viewModel = this.model; |       this.viewModel = this.model; | ||||||
|     } |     } | ||||||
|  | |||||||
| @ -9,7 +9,7 @@ import {isPresent} from 'angular2/src/core/facade/lang'; | |||||||
| import {setProperty} from './shared'; | import {setProperty} from './shared'; | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
|  * Marks <option> as dynamic, so Angular can be notified when options change. |  * Marks `<option>` as dynamic, so Angular can be notified when options change. | ||||||
|  * |  * | ||||||
|  * #Example: |  * #Example: | ||||||
|  * |  * | ||||||
| @ -53,7 +53,7 @@ export class SelectControlValueAccessor implements ControlValueAccessor { | |||||||
|     this._updateValueWhenListOfOptionsChanges(query); |     this._updateValueWhenListOfOptionsChanges(query); | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   writeValue(value: any) { |   writeValue(value: any): void { | ||||||
|     this.value = value; |     this.value = value; | ||||||
|     setProperty(this._renderer, this._elementRef, "value", value); |     setProperty(this._renderer, this._elementRef, "value", value); | ||||||
|   } |   } | ||||||
|  | |||||||
| @ -16,25 +16,25 @@ export function controlPath(name: string, parent: ControlContainer): string[] { | |||||||
|   return p; |   return p; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| export function setUpControl(c: Control, dir: NgControl) { | export function setUpControl(control: Control, dir: NgControl): void { | ||||||
|   if (isBlank(c)) _throwError(dir, "Cannot find control"); |   if (isBlank(control)) _throwError(dir, "Cannot find control"); | ||||||
|   if (isBlank(dir.valueAccessor)) _throwError(dir, "No value accessor for"); |   if (isBlank(dir.valueAccessor)) _throwError(dir, "No value accessor for"); | ||||||
| 
 | 
 | ||||||
|   c.validator = Validators.compose([c.validator, dir.validator]); |   control.validator = Validators.compose([control.validator, dir.validator]); | ||||||
|   dir.valueAccessor.writeValue(c.value); |   dir.valueAccessor.writeValue(control.value); | ||||||
| 
 | 
 | ||||||
|   // view -> model
 |   // view -> model
 | ||||||
|   dir.valueAccessor.registerOnChange(newValue => { |   dir.valueAccessor.registerOnChange(newValue => { | ||||||
|     dir.viewToModelUpdate(newValue); |     dir.viewToModelUpdate(newValue); | ||||||
|     c.updateValue(newValue, {emitModelToViewChange: false}); |     control.updateValue(newValue, {emitModelToViewChange: false}); | ||||||
|     c.markAsDirty(); |     control.markAsDirty(); | ||||||
|   }); |   }); | ||||||
| 
 | 
 | ||||||
|   // model -> view
 |   // model -> view
 | ||||||
|   c.registerOnChange(newValue => dir.valueAccessor.writeValue(newValue)); |   control.registerOnChange(newValue => dir.valueAccessor.writeValue(newValue)); | ||||||
| 
 | 
 | ||||||
|   // touched
 |   // touched
 | ||||||
|   dir.valueAccessor.registerOnTouched(() => c.markAsTouched()); |   dir.valueAccessor.registerOnTouched(() => control.markAsTouched()); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| function _throwError(dir: NgControl, message: string): void { | function _throwError(dir: NgControl, message: string): void { | ||||||
|  | |||||||
| @ -15,9 +15,7 @@ import * as modelModule from './model'; | |||||||
|  * |  * | ||||||
|  * @Component({ |  * @Component({ | ||||||
|  *   selector: 'login-comp', |  *   selector: 'login-comp', | ||||||
|  *   viewBindings: [ |  *   viewBindings: [FormBuilder] | ||||||
|  *     FormBuilder |  | ||||||
|  *   ] |  | ||||||
|  * }) |  * }) | ||||||
|  * @View({ |  * @View({ | ||||||
|  *   template: ` |  *   template: ` | ||||||
| @ -30,9 +28,7 @@ import * as modelModule from './model'; | |||||||
|  *       </div> |  *       </div> | ||||||
|  *     </form> |  *     </form> | ||||||
|  *   `,
 |  *   `,
 | ||||||
|  *   directives: [ |  *   directives: [FORM_DIRECTIVES] | ||||||
|  *     FORM_DIRECTIVES |  | ||||||
|  *   ] |  | ||||||
|  * }) |  * }) | ||||||
|  * class LoginComp { |  * class LoginComp { | ||||||
|  *   loginForm: ControlGroup; |  *   loginForm: ControlGroup; | ||||||
| @ -49,12 +45,12 @@ import * as modelModule from './model'; | |||||||
|  *   } |  *   } | ||||||
|  * } |  * } | ||||||
|  * |  * | ||||||
|  * bootstrap(LoginComp) |  * bootstrap(LoginComp); | ||||||
|  * ``` |  * ``` | ||||||
|  * |  * | ||||||
|  * This example creates a {@link ControlGroup} that consists of a `login` {@link Control}, and a |  * This example creates a {@link ControlGroup} that consists of a `login` {@link Control}, and a | ||||||
|  * nested |  * nested {@link ControlGroup} that defines a `password` and a `passwordConfirmation` | ||||||
|  * {@link ControlGroup} that defines a `password` and a `passwordConfirmation` {@link Control}: |  * {@link Control}: | ||||||
|  * |  * | ||||||
|  * ``` |  * ``` | ||||||
|  *  var loginForm = builder.group({ |  *  var loginForm = builder.group({ | ||||||
|  | |||||||
| @ -1,4 +1,4 @@ | |||||||
| import {StringWrapper, isPresent, isBlank} from 'angular2/src/core/facade/lang'; | import {StringWrapper, isPresent, isBlank, normalizeBool} from 'angular2/src/core/facade/lang'; | ||||||
| import {Observable, EventEmitter, ObservableWrapper} from 'angular2/src/core/facade/async'; | import {Observable, EventEmitter, ObservableWrapper} from 'angular2/src/core/facade/async'; | ||||||
| import {StringMap, StringMapWrapper, ListWrapper} from 'angular2/src/core/facade/collection'; | import {StringMap, StringMapWrapper, ListWrapper} from 'angular2/src/core/facade/collection'; | ||||||
| import {Validators} from './validators'; | import {Validators} from './validators'; | ||||||
| @ -13,14 +13,15 @@ export const VALID = "VALID"; | |||||||
|  */ |  */ | ||||||
| export const INVALID = "INVALID"; | export const INVALID = "INVALID"; | ||||||
| 
 | 
 | ||||||
| export function isControl(c: Object): boolean { | export function isControl(control: Object): boolean { | ||||||
|   return c instanceof AbstractControl; |   return control instanceof AbstractControl; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| function _find(c: AbstractControl, path: Array<string | number>| string) { | function _find(control: AbstractControl, path: Array<string | number>| string) { | ||||||
|   if (isBlank(path)) return null; |   if (isBlank(path)) return null; | ||||||
|  | 
 | ||||||
|   if (!(path instanceof Array)) { |   if (!(path instanceof Array)) { | ||||||
|     path = StringWrapper.split(<string>path, new RegExp("/")); |     path = (<string>path).split("/"); | ||||||
|   } |   } | ||||||
|   if (path instanceof Array && ListWrapper.isEmpty(path)) return null; |   if (path instanceof Array && ListWrapper.isEmpty(path)) return null; | ||||||
| 
 | 
 | ||||||
| @ -33,7 +34,7 @@ function _find(c: AbstractControl, path: Array<string | number>| string) { | |||||||
|     } else { |     } else { | ||||||
|       return null; |       return null; | ||||||
|     } |     } | ||||||
|   }, c); |   }, control); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
| @ -43,18 +44,13 @@ export class AbstractControl { | |||||||
|   _value: any; |   _value: any; | ||||||
|   _status: string; |   _status: string; | ||||||
|   _errors: StringMap<string, any>; |   _errors: StringMap<string, any>; | ||||||
|   _pristine: boolean; |   _pristine: boolean = true; | ||||||
|   _touched: boolean; |   _touched: boolean = false; | ||||||
|   _parent: ControlGroup | ControlArray; |   _parent: ControlGroup | ControlArray; | ||||||
|   validator: Function; |  | ||||||
| 
 | 
 | ||||||
|   _valueChanges: EventEmitter; |   _valueChanges: EventEmitter; | ||||||
| 
 | 
 | ||||||
|   constructor(validator: Function) { |   constructor(public validator: Function) {} | ||||||
|     this.validator = validator; |  | ||||||
|     this._pristine = true; |  | ||||||
|     this._touched = false; |  | ||||||
|   } |  | ||||||
| 
 | 
 | ||||||
|   get value(): any { return this._value; } |   get value(): any { return this._value; } | ||||||
| 
 | 
 | ||||||
| @ -77,18 +73,18 @@ export class AbstractControl { | |||||||
|   markAsTouched(): void { this._touched = true; } |   markAsTouched(): void { this._touched = true; } | ||||||
| 
 | 
 | ||||||
|   markAsDirty({onlySelf}: {onlySelf?: boolean} = {}): void { |   markAsDirty({onlySelf}: {onlySelf?: boolean} = {}): void { | ||||||
|     onlySelf = isPresent(onlySelf) ? onlySelf : false; |     onlySelf = normalizeBool(onlySelf); | ||||||
| 
 |  | ||||||
|     this._pristine = false; |     this._pristine = false; | ||||||
|  | 
 | ||||||
|     if (isPresent(this._parent) && !onlySelf) { |     if (isPresent(this._parent) && !onlySelf) { | ||||||
|       this._parent.markAsDirty({onlySelf: onlySelf}); |       this._parent.markAsDirty({onlySelf: onlySelf}); | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   setParent(parent: ControlGroup | ControlArray) { this._parent = parent; } |   setParent(parent: ControlGroup | ControlArray): void { this._parent = parent; } | ||||||
| 
 | 
 | ||||||
|   updateValidity({onlySelf}: {onlySelf?: boolean} = {}): void { |   updateValidity({onlySelf}: {onlySelf?: boolean} = {}): void { | ||||||
|     onlySelf = isPresent(onlySelf) ? onlySelf : false; |     onlySelf = normalizeBool(onlySelf); | ||||||
| 
 | 
 | ||||||
|     this._errors = this.validator(this); |     this._errors = this.validator(this); | ||||||
|     this._status = isPresent(this._errors) ? INVALID : VALID; |     this._status = isPresent(this._errors) ? INVALID : VALID; | ||||||
| @ -100,7 +96,7 @@ export class AbstractControl { | |||||||
| 
 | 
 | ||||||
|   updateValueAndValidity({onlySelf, emitEvent}: {onlySelf?: boolean, emitEvent?: boolean} = {}): |   updateValueAndValidity({onlySelf, emitEvent}: {onlySelf?: boolean, emitEvent?: boolean} = {}): | ||||||
|       void { |       void { | ||||||
|     onlySelf = isPresent(onlySelf) ? onlySelf : false; |     onlySelf = normalizeBool(onlySelf); | ||||||
|     emitEvent = isPresent(emitEvent) ? emitEvent : true; |     emitEvent = isPresent(emitEvent) ? emitEvent : true; | ||||||
| 
 | 
 | ||||||
|     this._updateValue(); |     this._updateValue(); | ||||||
| @ -111,6 +107,7 @@ export class AbstractControl { | |||||||
| 
 | 
 | ||||||
|     this._errors = this.validator(this); |     this._errors = this.validator(this); | ||||||
|     this._status = isPresent(this._errors) ? INVALID : VALID; |     this._status = isPresent(this._errors) ? INVALID : VALID; | ||||||
|  | 
 | ||||||
|     if (isPresent(this._parent) && !onlySelf) { |     if (isPresent(this._parent) && !onlySelf) { | ||||||
|       this._parent.updateValueAndValidity({onlySelf: onlySelf, emitEvent: emitEvent}); |       this._parent.updateValueAndValidity({onlySelf: onlySelf, emitEvent: emitEvent}); | ||||||
|     } |     } | ||||||
| @ -119,9 +116,9 @@ export class AbstractControl { | |||||||
|   find(path: Array<string | number>| string): AbstractControl { return _find(this, path); } |   find(path: Array<string | number>| string): AbstractControl { return _find(this, path); } | ||||||
| 
 | 
 | ||||||
|   getError(errorCode: string, path: string[] = null): any { |   getError(errorCode: string, path: string[] = null): any { | ||||||
|     var c = isPresent(path) && !ListWrapper.isEmpty(path) ? this.find(path) : this; |     var control = isPresent(path) && !ListWrapper.isEmpty(path) ? this.find(path) : this; | ||||||
|     if (isPresent(c) && isPresent(c._errors)) { |     if (isPresent(control) && isPresent(control._errors)) { | ||||||
|       return StringMapWrapper.get(c._errors, errorCode); |       return StringMapWrapper.get(control._errors, errorCode); | ||||||
|     } else { |     } else { | ||||||
|       return null; |       return null; | ||||||
|     } |     } | ||||||
| @ -138,8 +135,7 @@ export class AbstractControl { | |||||||
|  * Defines a part of a form that cannot be divided into other controls. |  * Defines a part of a form that cannot be divided into other controls. | ||||||
|  * |  * | ||||||
|  * `Control` is one of the three fundamental building blocks used to define forms in Angular, along |  * `Control` is one of the three fundamental building blocks used to define forms in Angular, along | ||||||
|  * with |  * with {@link ControlGroup} and {@link ControlArray}. | ||||||
|  * {@link ControlGroup} and {@link ControlArray}. |  | ||||||
|  */ |  */ | ||||||
| export class Control extends AbstractControl { | export class Control extends AbstractControl { | ||||||
|   _onChange: Function; |   _onChange: Function; | ||||||
| @ -167,29 +163,22 @@ export class Control extends AbstractControl { | |||||||
| /** | /** | ||||||
|  * Defines a part of a form, of fixed length, that can contain other controls. |  * Defines a part of a form, of fixed length, that can contain other controls. | ||||||
|  * |  * | ||||||
|  * A ControlGroup aggregates the values and errors of each {@link Control} in the group. Thus, if |  * A `ControlGroup` aggregates the values and errors of each {@link Control} in the group. Thus, if | ||||||
|  * one of the controls |  * one of the controls in a group is invalid, the entire group is invalid. Similarly, if a control | ||||||
|  * in a group is invalid, the entire group is invalid. Similarly, if a control changes its value, |  * changes its value, the entire group changes as well. | ||||||
|  * the entire group |  | ||||||
|  * changes as well. |  | ||||||
|  * |  * | ||||||
|  * `ControlGroup` is one of the three fundamental building blocks used to define forms in Angular, |  * `ControlGroup` is one of the three fundamental building blocks used to define forms in Angular, | ||||||
|  * along with |  * along with {@link Control} and {@link ControlArray}. {@link ControlArray} can also contain other | ||||||
|  * {@link Control} and {@link ControlArray}. {@link ControlArray} can also contain other controls, |  * controls, but is of variable length. | ||||||
|  * but is of variable |  | ||||||
|  * length. |  | ||||||
|  */ |  */ | ||||||
| export class ControlGroup extends AbstractControl { | export class ControlGroup extends AbstractControl { | ||||||
|   controls: StringMap<string, AbstractControl>; |   private _optionals: StringMap<string, boolean>; | ||||||
|   _optionals: StringMap<string, boolean>; |  | ||||||
| 
 | 
 | ||||||
|   constructor(controls: StringMap<string, AbstractControl>, |   constructor(public controls: StringMap<string, AbstractControl>, | ||||||
|               optionals: StringMap<string, boolean> = null, |               optionals: StringMap<string, boolean> = null, | ||||||
|               validator: Function = Validators.group) { |               validator: Function = Validators.group) { | ||||||
|     super(validator); |     super(validator); | ||||||
|     this.controls = controls; |  | ||||||
|     this._optionals = isPresent(optionals) ? optionals : {}; |     this._optionals = isPresent(optionals) ? optionals : {}; | ||||||
| 
 |  | ||||||
|     this._valueChanges = new EventEmitter(); |     this._valueChanges = new EventEmitter(); | ||||||
| 
 | 
 | ||||||
|     this._setParentForControls(); |     this._setParentForControls(); | ||||||
| @ -197,12 +186,12 @@ export class ControlGroup extends AbstractControl { | |||||||
|     this.updateValidity({onlySelf: true}); |     this.updateValidity({onlySelf: true}); | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   addControl(name: string, c: AbstractControl) { |   addControl(name: string, control: AbstractControl): void { | ||||||
|     this.controls[name] = c; |     this.controls[name] = control; | ||||||
|     c.setParent(this); |     control.setParent(this); | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   removeControl(name: string) { StringMapWrapper.delete(this.controls, name); } |   removeControl(name: string): void { StringMapWrapper.delete(this.controls, name); } | ||||||
| 
 | 
 | ||||||
|   include(controlName: string): void { |   include(controlName: string): void { | ||||||
|     StringMapWrapper.set(this._optionals, controlName, true); |     StringMapWrapper.set(this._optionals, controlName, true); | ||||||
| @ -252,21 +241,16 @@ export class ControlGroup extends AbstractControl { | |||||||
|  * Defines a part of a form, of variable length, that can contain other controls. |  * Defines a part of a form, of variable length, that can contain other controls. | ||||||
|  * |  * | ||||||
|  * A `ControlArray` aggregates the values and errors of each {@link Control} in the group. Thus, if |  * A `ControlArray` aggregates the values and errors of each {@link Control} in the group. Thus, if | ||||||
|  * one of the controls |  * one of the controls in a group is invalid, the entire group is invalid. Similarly, if a control | ||||||
|  * in a group is invalid, the entire group is invalid. Similarly, if a control changes its value, |  * changes its value, the entire group changes as well. | ||||||
|  * the entire group |  | ||||||
|  * changes as well. |  | ||||||
|  * |  * | ||||||
|  * `ControlArray` is one of the three fundamental building blocks used to define forms in Angular, |  * `ControlArray` is one of the three fundamental building blocks used to define forms in Angular, | ||||||
|  * along with {@link Control} and {@link ControlGroup}. {@link ControlGroup} can also contain |  * along with {@link Control} and {@link ControlGroup}. {@link ControlGroup} can also contain | ||||||
|  * other controls, but is of fixed length. |  * other controls, but is of fixed length. | ||||||
|  */ |  */ | ||||||
| export class ControlArray extends AbstractControl { | export class ControlArray extends AbstractControl { | ||||||
|   controls: AbstractControl[]; |   constructor(public controls: AbstractControl[], validator: Function = Validators.array) { | ||||||
| 
 |  | ||||||
|   constructor(controls: AbstractControl[], validator: Function = Validators.array) { |  | ||||||
|     super(validator); |     super(validator); | ||||||
|     this.controls = controls; |  | ||||||
| 
 | 
 | ||||||
|     this._valueChanges = new EventEmitter(); |     this._valueChanges = new EventEmitter(); | ||||||
| 
 | 
 | ||||||
| @ -296,9 +280,9 @@ export class ControlArray extends AbstractControl { | |||||||
| 
 | 
 | ||||||
|   get length(): number { return this.controls.length; } |   get length(): number { return this.controls.length; } | ||||||
| 
 | 
 | ||||||
|   _updateValue() { this._value = ListWrapper.map(this.controls, (c) => c.value); } |   _updateValue(): void { this._value = this.controls.map((control) => control.value); } | ||||||
| 
 | 
 | ||||||
|   _setParentForControls() { |   _setParentForControls(): void { | ||||||
|     ListWrapper.forEach(this.controls, (control) => { control.setParent(this); }); |     this.controls.forEach((control) => { control.setParent(this); }); | ||||||
|   } |   } | ||||||
| } | } | ||||||
|  | |||||||
| @ -17,8 +17,8 @@ export const NG_VALIDATORS: OpaqueToken = CONST_EXPR(new OpaqueToken("NgValidato | |||||||
|  * ``` |  * ``` | ||||||
|  */ |  */ | ||||||
| export class Validators { | export class Validators { | ||||||
|   static required(c: modelModule.Control): StringMap<string, boolean> { |   static required(control: modelModule.Control): StringMap<string, boolean> { | ||||||
|     return isBlank(c.value) || c.value == "" ? {"required": true} : null; |     return isBlank(control.value) || control.value == "" ? {"required": true} : null; | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   static nullValidator(c: any): StringMap<string, boolean> { return null; } |   static nullValidator(c: any): StringMap<string, boolean> { return null; } | ||||||
| @ -26,28 +26,28 @@ export class Validators { | |||||||
|   static compose(validators: Function[]): Function { |   static compose(validators: Function[]): Function { | ||||||
|     if (isBlank(validators)) return Validators.nullValidator; |     if (isBlank(validators)) return Validators.nullValidator; | ||||||
| 
 | 
 | ||||||
|     return function(c: modelModule.Control) { |     return function(control: modelModule.Control) { | ||||||
|       var res = ListWrapper.reduce(validators, (res, validator) => { |       var res = ListWrapper.reduce(validators, (res, validator) => { | ||||||
|         var errors = validator(c); |         var errors = validator(control); | ||||||
|         return isPresent(errors) ? StringMapWrapper.merge(res, errors) : res; |         return isPresent(errors) ? StringMapWrapper.merge(res, errors) : res; | ||||||
|       }, {}); |       }, {}); | ||||||
|       return StringMapWrapper.isEmpty(res) ? null : res; |       return StringMapWrapper.isEmpty(res) ? null : res; | ||||||
|     }; |     }; | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   static group(c: modelModule.ControlGroup): StringMap<string, boolean> { |   static group(group: modelModule.ControlGroup): StringMap<string, boolean> { | ||||||
|     var res = {}; |     var res = {}; | ||||||
|     StringMapWrapper.forEach(c.controls, (control, name) => { |     StringMapWrapper.forEach(group.controls, (control, name) => { | ||||||
|       if (c.contains(name) && isPresent(control.errors)) { |       if (group.contains(name) && isPresent(control.errors)) { | ||||||
|         Validators._mergeErrors(control, res); |         Validators._mergeErrors(control, res); | ||||||
|       } |       } | ||||||
|     }); |     }); | ||||||
|     return StringMapWrapper.isEmpty(res) ? null : res; |     return StringMapWrapper.isEmpty(res) ? null : res; | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   static array(c: modelModule.ControlArray): StringMap<string, boolean> { |   static array(array: modelModule.ControlArray): StringMap<string, boolean> { | ||||||
|     var res = {}; |     var res = {}; | ||||||
|     ListWrapper.forEach(c.controls, (control) => { |     array.controls.forEach((control) => { | ||||||
|       if (isPresent(control.errors)) { |       if (isPresent(control.errors)) { | ||||||
|         Validators._mergeErrors(control, res); |         Validators._mergeErrors(control, res); | ||||||
|       } |       } | ||||||
|  | |||||||
| @ -19,7 +19,7 @@ import {RegExpWrapper, print, isPresent} from 'angular2/src/core/facade/lang'; | |||||||
|  * Custom validator. |  * Custom validator. | ||||||
|  */ |  */ | ||||||
| function creditCardValidator(c): StringMap<string, boolean> { | function creditCardValidator(c): StringMap<string, boolean> { | ||||||
|   if (isPresent(c.value) && RegExpWrapper.test(new RegExp("^\\d{16}$"), c.value)) { |   if (isPresent(c.value) && RegExpWrapper.test(/^\d{16}$/g, c.value)) { | ||||||
|     return null; |     return null; | ||||||
|   } else { |   } else { | ||||||
|     return {"invalidCreditCard": true}; |     return {"invalidCreditCard": true}; | ||||||
| @ -55,17 +55,19 @@ class ShowError { | |||||||
| 
 | 
 | ||||||
|   constructor(@Host() formDir: NgFormModel) { this.formDir = formDir; } |   constructor(@Host() formDir: NgFormModel) { this.formDir = formDir; } | ||||||
| 
 | 
 | ||||||
|   get errorMessage() { |   get errorMessage(): string { | ||||||
|     var c = this.formDir.form.find(this.controlPath); |     var control = this.formDir.form.find(this.controlPath); | ||||||
|     for (var i = 0; i < this.errorTypes.length; ++i) { |     if (isPresent(control) && control.touched) { | ||||||
|       if (isPresent(c) && c.touched && c.hasError(this.errorTypes[i])) { |       for (var i = 0; i < this.errorTypes.length; ++i) { | ||||||
|         return this._errorMessage(this.errorTypes[i]); |         if (control.hasError(this.errorTypes[i])) { | ||||||
|  |           return this._errorMessage(this.errorTypes[i]); | ||||||
|  |         } | ||||||
|       } |       } | ||||||
|     } |     } | ||||||
|     return null; |     return null; | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   _errorMessage(code) { |   _errorMessage(code: string): string { | ||||||
|     var config = {'required': 'is required', 'invalidCreditCard': 'is invalid credit card number'}; |     var config = {'required': 'is required', 'invalidCreditCard': 'is invalid credit card number'}; | ||||||
|     return config[code]; |     return config[code]; | ||||||
|   } |   } | ||||||
| @ -148,7 +150,7 @@ class ModelDrivenForms { | |||||||
|     }); |     }); | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   onSubmit() { |   onSubmit(): void { | ||||||
|     print("Submitting:"); |     print("Submitting:"); | ||||||
|     print(this.form.value); |     print(this.form.value); | ||||||
|   } |   } | ||||||
|  | |||||||
| @ -36,7 +36,7 @@ class CheckoutModel { | |||||||
|  * Custom validator. |  * Custom validator. | ||||||
|  */ |  */ | ||||||
| function creditCardValidator(c): StringMap<string, boolean> { | function creditCardValidator(c): StringMap<string, boolean> { | ||||||
|   if (isPresent(c.value) && RegExpWrapper.test(new RegExp("^\\d{16}$"), c.value)) { |   if (isPresent(c.value) && RegExpWrapper.test(/^\d{16}$/g, c.value)) { | ||||||
|     return null; |     return null; | ||||||
|   } else { |   } else { | ||||||
|     return {"invalidCreditCard": true}; |     return {"invalidCreditCard": true}; | ||||||
| @ -79,17 +79,19 @@ class ShowError { | |||||||
| 
 | 
 | ||||||
|   constructor(@Host() formDir: NgForm) { this.formDir = formDir; } |   constructor(@Host() formDir: NgForm) { this.formDir = formDir; } | ||||||
| 
 | 
 | ||||||
|   get errorMessage() { |   get errorMessage(): string { | ||||||
|     var c = this.formDir.form.find(this.controlPath); |     var control = this.formDir.form.find(this.controlPath); | ||||||
|     for (var i = 0; i < this.errorTypes.length; ++i) { |     if (isPresent(control) && control.touched) { | ||||||
|       if (isPresent(c) && c.touched && c.hasError(this.errorTypes[i])) { |       for (var i = 0; i < this.errorTypes.length; ++i) { | ||||||
|         return this._errorMessage(this.errorTypes[i]); |         if (control.hasError(this.errorTypes[i])) { | ||||||
|  |           return this._errorMessage(this.errorTypes[i]); | ||||||
|  |         } | ||||||
|       } |       } | ||||||
|     } |     } | ||||||
|     return null; |     return null; | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   _errorMessage(code) { |   _errorMessage(code: string): string { | ||||||
|     var config = {'required': 'is required', 'invalidCreditCard': 'is invalid credit card number'}; |     var config = {'required': 'is required', 'invalidCreditCard': 'is invalid credit card number'}; | ||||||
|     return config[code]; |     return config[code]; | ||||||
|   } |   } | ||||||
| @ -159,7 +161,7 @@ class TemplateDrivenForms { | |||||||
|   model = new CheckoutModel(); |   model = new CheckoutModel(); | ||||||
|   countries = ['US', 'Canada']; |   countries = ['US', 'Canada']; | ||||||
| 
 | 
 | ||||||
|   onSubmit() { |   onSubmit(): void { | ||||||
|     print("Submitting:"); |     print("Submitting:"); | ||||||
|     print(this.model); |     print(this.model); | ||||||
|   } |   } | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user