| 
									
										
										
										
											2016-06-23 09:47:54 -07:00
										 |  |  | /** | 
					
						
							|  |  |  |  * @license | 
					
						
							|  |  |  |  * Copyright Google Inc. All Rights Reserved. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Use of this source code is governed by an MIT-style license that can be | 
					
						
							|  |  |  |  * found in the LICENSE file at https://angular.io/license
 | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  | import {Injectable} from '@angular/core'; | 
					
						
							| 
									
										
										
										
											2016-06-08 16:38:52 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | import {AsyncValidatorFn, ValidatorFn} from './directives/validators'; | 
					
						
							| 
									
										
										
										
											2016-06-14 18:23:40 -07:00
										 |  |  | import {StringMapWrapper} from './facade/collection'; | 
					
						
							|  |  |  | import {isArray, isPresent} from './facade/lang'; | 
					
						
							| 
									
										
										
										
											2016-06-22 14:56:10 -07:00
										 |  |  | import {AbstractControl, FormArray, FormControl, FormGroup} from './model'; | 
					
						
							| 
									
										
										
										
											2016-06-08 16:38:52 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /** | 
					
						
							|  |  |  |  * Creates a form object from a user-specified configuration. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * ```typescript
 | 
					
						
							|  |  |  |  * @Component({ | 
					
						
							|  |  |  |  *   selector: 'my-app', | 
					
						
							|  |  |  |  *   template: `
 | 
					
						
							| 
									
										
										
										
											2016-06-10 19:10:17 -07:00
										 |  |  |  *     <form [formGroup]="loginForm"> | 
					
						
							| 
									
										
										
										
											2016-06-12 13:17:07 -07:00
										 |  |  |  *       <p>Login <input formControlName="login"></p> | 
					
						
							| 
									
										
										
										
											2016-06-12 16:37:42 -07:00
										 |  |  |  *       <div formGroupName="passwordRetry"> | 
					
						
							| 
									
										
										
										
											2016-06-12 13:17:07 -07:00
										 |  |  |  *         <p>Password <input type="password" formControlName="password"></p> | 
					
						
							|  |  |  |  *         <p>Confirm password <input type="password" formControlName="passwordConfirmation"></p> | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  |  *       </div> | 
					
						
							|  |  |  |  *     </form> | 
					
						
							|  |  |  |  *     <h3>Form value:</h3> | 
					
						
							|  |  |  |  *     <pre>{{value}}</pre> | 
					
						
							|  |  |  |  *   `,
 | 
					
						
							| 
									
										
										
										
											2016-06-12 13:17:07 -07:00
										 |  |  |  *   directives: [REACTIVE_FORM_DIRECTIVES] | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  |  * }) | 
					
						
							|  |  |  |  * export class App { | 
					
						
							| 
									
										
										
										
											2016-06-10 11:15:59 -07:00
										 |  |  |  *   loginForm: FormGroup; | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  |  * | 
					
						
							|  |  |  |  *   constructor(builder: FormBuilder) { | 
					
						
							|  |  |  |  *     this.loginForm = builder.group({ | 
					
						
							|  |  |  |  *       login: ["", Validators.required], | 
					
						
							|  |  |  |  *       passwordRetry: builder.group({ | 
					
						
							|  |  |  |  *         password: ["", Validators.required], | 
					
						
							|  |  |  |  *         passwordConfirmation: ["", Validators.required, asyncValidator] | 
					
						
							|  |  |  |  *       }) | 
					
						
							|  |  |  |  *     }); | 
					
						
							|  |  |  |  *   } | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  *   get value(): string { | 
					
						
							|  |  |  |  *     return JSON.stringify(this.loginForm.value, null, 2); | 
					
						
							|  |  |  |  *   } | 
					
						
							|  |  |  |  * } | 
					
						
							|  |  |  |  * ```
 | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * @experimental | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | @Injectable() | 
					
						
							|  |  |  | export class FormBuilder { | 
					
						
							|  |  |  |   /** | 
					
						
							| 
									
										
										
										
											2016-06-10 11:15:59 -07:00
										 |  |  |    * Construct a new {@link FormGroup} with the given map of configuration. | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  |    * Valid keys for the `extra` parameter map are `optionals` and `validator`. | 
					
						
							|  |  |  |    * | 
					
						
							| 
									
										
										
										
											2016-06-10 11:15:59 -07:00
										 |  |  |    * See the {@link FormGroup} constructor for more details. | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  |    */ | 
					
						
							| 
									
										
										
										
											2016-06-22 14:56:10 -07:00
										 |  |  |   group(controlsConfig: {[key: string]: any}, extra: {[key: string]: any} = null): FormGroup { | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  |     var controls = this._reduceControls(controlsConfig); | 
					
						
							|  |  |  |     var optionals = <{[key: string]: boolean}>( | 
					
						
							| 
									
										
										
										
											2016-06-08 16:38:52 -07:00
										 |  |  |         isPresent(extra) ? StringMapWrapper.get(extra, 'optionals') : null); | 
					
						
							|  |  |  |     var validator: ValidatorFn = isPresent(extra) ? StringMapWrapper.get(extra, 'validator') : null; | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  |     var asyncValidator: AsyncValidatorFn = | 
					
						
							| 
									
										
										
										
											2016-06-08 16:38:52 -07:00
										 |  |  |         isPresent(extra) ? StringMapWrapper.get(extra, 'asyncValidator') : null; | 
					
						
							| 
									
										
										
										
											2016-06-22 14:56:10 -07:00
										 |  |  |     return new FormGroup(controls, optionals, validator, asyncValidator); | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  |   } | 
					
						
							|  |  |  |   /** | 
					
						
							| 
									
										
										
										
											2016-06-10 11:15:59 -07:00
										 |  |  |    * Construct a new {@link FormControl} with the given `value`,`validator`, and `asyncValidator`. | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  |    */ | 
					
						
							| 
									
										
										
										
											2016-06-13 11:27:04 -07:00
										 |  |  |   control( | 
					
						
							|  |  |  |       value: Object, validator: ValidatorFn|ValidatorFn[] = null, | 
					
						
							| 
									
										
										
										
											2016-06-22 14:56:10 -07:00
										 |  |  |       asyncValidator: AsyncValidatorFn|AsyncValidatorFn[] = null): FormControl { | 
					
						
							|  |  |  |     return new FormControl(value, validator, asyncValidator); | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /** | 
					
						
							| 
									
										
										
										
											2016-06-10 11:15:59 -07:00
										 |  |  |    * Construct an array of {@link FormControl}s from the given `controlsConfig` array of | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  |    * configuration, with the given optional `validator` and `asyncValidator`. | 
					
						
							|  |  |  |    */ | 
					
						
							| 
									
										
										
										
											2016-06-08 16:38:52 -07:00
										 |  |  |   array( | 
					
						
							|  |  |  |       controlsConfig: any[], validator: ValidatorFn = null, | 
					
						
							| 
									
										
										
										
											2016-06-22 14:56:10 -07:00
										 |  |  |       asyncValidator: AsyncValidatorFn = null): FormArray { | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  |     var controls = controlsConfig.map(c => this._createControl(c)); | 
					
						
							| 
									
										
										
										
											2016-06-22 14:56:10 -07:00
										 |  |  |     return new FormArray(controls, validator, asyncValidator); | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /** @internal */ | 
					
						
							| 
									
										
										
										
											2016-06-22 14:56:10 -07:00
										 |  |  |   _reduceControls(controlsConfig: {[k: string]: any}): {[key: string]: AbstractControl} { | 
					
						
							|  |  |  |     var controls: {[key: string]: AbstractControl} = {}; | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  |     StringMapWrapper.forEach(controlsConfig, (controlConfig: any, controlName: string) => { | 
					
						
							|  |  |  |       controls[controlName] = this._createControl(controlConfig); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |     return controls; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /** @internal */ | 
					
						
							| 
									
										
										
										
											2016-06-22 14:56:10 -07:00
										 |  |  |   _createControl(controlConfig: any): AbstractControl { | 
					
						
							|  |  |  |     if (controlConfig instanceof FormControl || controlConfig instanceof FormGroup || | 
					
						
							|  |  |  |         controlConfig instanceof FormArray) { | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  |       return controlConfig; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     } else if (isArray(controlConfig)) { | 
					
						
							|  |  |  |       var value = controlConfig[0]; | 
					
						
							|  |  |  |       var validator: ValidatorFn = controlConfig.length > 1 ? controlConfig[1] : null; | 
					
						
							|  |  |  |       var asyncValidator: AsyncValidatorFn = controlConfig.length > 2 ? controlConfig[2] : null; | 
					
						
							|  |  |  |       return this.control(value, validator, asyncValidator); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |       return this.control(controlConfig); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } |