| 
									
										
										
										
											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
 | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-16 10:15:17 -07:00
										 |  |  | import {EventEmitter} from '@angular/core'; | 
					
						
							| 
									
										
										
										
											2018-02-27 17:06:06 -05:00
										 |  |  | import {Observable} from 'rxjs'; | 
					
						
							| 
									
										
										
										
											2016-06-13 11:27:04 -07:00
										 |  |  | import {composeAsyncValidators, composeValidators} from './directives/shared'; | 
					
						
							| 
									
										
										
										
											2017-02-23 20:53:29 +03:00
										 |  |  | import {AsyncValidatorFn, ValidationErrors, ValidatorFn} from './directives/validators'; | 
					
						
							| 
									
										
										
										
											2017-03-16 10:15:17 -07:00
										 |  |  | import {toObservable} from './validators'; | 
					
						
							| 
									
										
										
										
											2017-02-01 15:41:14 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  | /** | 
					
						
							| 
									
										
										
										
											2018-06-11 14:24:00 -05:00
										 |  |  |  * Reports that a FormControl is valid, meaning that no errors exist in the input value. | 
					
						
							| 
									
										
										
										
											2018-06-07 13:31:25 -05:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2018-06-11 14:24:00 -05:00
										 |  |  |  * @see `status` | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  |  */ | 
					
						
							| 
									
										
										
										
											2016-06-08 16:38:52 -07:00
										 |  |  | export const VALID = 'VALID'; | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | /** | 
					
						
							| 
									
										
										
										
											2018-06-11 14:24:00 -05:00
										 |  |  |  * Reports that a FormControl is invalid, meaning that an error exists in the input value. | 
					
						
							| 
									
										
										
										
											2018-06-11 15:48:35 -05:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2018-06-11 14:24:00 -05:00
										 |  |  |  * @see `status` | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  |  */ | 
					
						
							| 
									
										
										
										
											2016-06-08 16:38:52 -07:00
										 |  |  | export const INVALID = 'INVALID'; | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | /** | 
					
						
							| 
									
										
										
										
											2018-06-11 14:24:00 -05:00
										 |  |  |  * Reports that a FormControl is pending, meaning that that async validation is occurring and | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  |  * errors are not yet available for the input value. | 
					
						
							| 
									
										
										
										
											2018-06-11 15:48:35 -05:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2018-06-07 13:31:25 -05:00
										 |  |  |  * @see `markAsPending` | 
					
						
							| 
									
										
										
										
											2018-06-11 14:24:00 -05:00
										 |  |  |  * @see `status` | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  |  */ | 
					
						
							| 
									
										
										
										
											2016-06-08 16:38:52 -07:00
										 |  |  | export const PENDING = 'PENDING'; | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-24 16:58:43 -07:00
										 |  |  | /** | 
					
						
							| 
									
										
										
										
											2018-06-11 14:24:00 -05:00
										 |  |  |  * Reports that a FormControl is disabled, meaning that the control is exempt from ancestor | 
					
						
							| 
									
										
										
										
											2016-08-24 16:58:43 -07:00
										 |  |  |  * calculations of validity or value. | 
					
						
							| 
									
										
										
										
											2018-06-11 15:48:35 -05:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2018-06-07 13:31:25 -05:00
										 |  |  |  * @see `markAsDisabled` | 
					
						
							| 
									
										
										
										
											2018-06-11 14:24:00 -05:00
										 |  |  |  * @see `status` | 
					
						
							| 
									
										
										
										
											2016-08-24 16:58:43 -07:00
										 |  |  |  */ | 
					
						
							|  |  |  | export const DISABLED = 'DISABLED'; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-01 14:22:50 -07:00
										 |  |  | function _find(control: AbstractControl, path: Array<string|number>| string, delimiter: string) { | 
					
						
							| 
									
										
										
										
											2016-10-21 15:14:44 -07:00
										 |  |  |   if (path == null) return null; | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |   if (!(path instanceof Array)) { | 
					
						
							| 
									
										
										
										
											2016-08-01 14:22:50 -07:00
										 |  |  |     path = (<string>path).split(delimiter); | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2016-10-19 19:55:50 +03:00
										 |  |  |   if (path instanceof Array && (path.length === 0)) return null; | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-04-17 11:13:30 -07:00
										 |  |  |   return (<Array<string|number>>path).reduce((v: AbstractControl, name) => { | 
					
						
							| 
									
										
										
										
											2016-06-10 11:15:59 -07:00
										 |  |  |     if (v instanceof FormGroup) { | 
					
						
							| 
									
										
										
										
											2018-04-07 15:11:02 +08:00
										 |  |  |       return v.controls.hasOwnProperty(name as string) ? v.controls[name] : null; | 
					
						
							| 
									
										
										
										
											2016-06-08 16:38:52 -07:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2016-10-07 18:11:37 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if (v instanceof FormArray) { | 
					
						
							|  |  |  |       return v.at(<number>name) || null; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return null; | 
					
						
							| 
									
										
										
										
											2016-06-08 16:38:52 -07:00
										 |  |  |   }, control); | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2017-02-23 20:53:29 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-25 15:01:04 -07:00
										 |  |  | function coerceToValidator( | 
					
						
							|  |  |  |     validatorOrOpts?: ValidatorFn | ValidatorFn[] | AbstractControlOptions | null): ValidatorFn| | 
					
						
							|  |  |  |     null { | 
					
						
							|  |  |  |   const validator = | 
					
						
							|  |  |  |       (isOptionsObj(validatorOrOpts) ? (validatorOrOpts as AbstractControlOptions).validators : | 
					
						
							|  |  |  |                                        validatorOrOpts) as ValidatorFn | | 
					
						
							|  |  |  |       ValidatorFn[] | null; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-04-17 11:13:30 -07:00
										 |  |  |   return Array.isArray(validator) ? composeValidators(validator) : validator || null; | 
					
						
							| 
									
										
										
										
											2016-06-13 11:27:04 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-25 15:01:04 -07:00
										 |  |  | function coerceToAsyncValidator( | 
					
						
							|  |  |  |     asyncValidator?: AsyncValidatorFn | AsyncValidatorFn[] | null, validatorOrOpts?: ValidatorFn | | 
					
						
							|  |  |  |         ValidatorFn[] | AbstractControlOptions | null): AsyncValidatorFn|null { | 
					
						
							|  |  |  |   const origAsyncValidator = | 
					
						
							|  |  |  |       (isOptionsObj(validatorOrOpts) ? (validatorOrOpts as AbstractControlOptions).asyncValidators : | 
					
						
							|  |  |  |                                        asyncValidator) as AsyncValidatorFn | | 
					
						
							|  |  |  |       AsyncValidatorFn | null; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return Array.isArray(origAsyncValidator) ? composeAsyncValidators(origAsyncValidator) : | 
					
						
							|  |  |  |                                              origAsyncValidator || null; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-07 15:39:25 -07:00
										 |  |  | export type FormHooks = 'change' | 'blur' | 'submit'; | 
					
						
							| 
									
										
										
										
											2017-08-02 18:10:10 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-01 11:25:14 +08:00
										 |  |  | /** | 
					
						
							| 
									
										
										
										
											2018-04-05 10:58:12 +01:00
										 |  |  |  * Interface for options provided to an `AbstractControl`. | 
					
						
							| 
									
										
										
										
											2018-02-01 11:25:14 +08:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2018-10-19 12:12:20 +01:00
										 |  |  |  * @publicApi | 
					
						
							| 
									
										
										
										
											2018-02-01 11:25:14 +08:00
										 |  |  |  */ | 
					
						
							| 
									
										
										
										
											2017-07-25 15:01:04 -07:00
										 |  |  | export interface AbstractControlOptions { | 
					
						
							| 
									
										
										
										
											2018-02-01 11:25:14 +08:00
										 |  |  |   /** | 
					
						
							| 
									
										
										
										
											2018-11-01 13:51:37 -05:00
										 |  |  |    * @description | 
					
						
							|  |  |  |    * The list of validators applied to a control. | 
					
						
							| 
									
										
										
										
											2018-02-01 11:25:14 +08:00
										 |  |  |    */ | 
					
						
							| 
									
										
										
										
											2017-07-25 15:01:04 -07:00
										 |  |  |   validators?: ValidatorFn|ValidatorFn[]|null; | 
					
						
							| 
									
										
										
										
											2018-02-01 11:25:14 +08:00
										 |  |  |   /** | 
					
						
							| 
									
										
										
										
											2018-11-01 13:51:37 -05:00
										 |  |  |    * @description | 
					
						
							|  |  |  |    * The list of async validators applied to control. | 
					
						
							| 
									
										
										
										
											2018-02-01 11:25:14 +08:00
										 |  |  |    */ | 
					
						
							| 
									
										
										
										
											2017-07-25 15:01:04 -07:00
										 |  |  |   asyncValidators?: AsyncValidatorFn|AsyncValidatorFn[]|null; | 
					
						
							| 
									
										
										
										
											2018-02-01 11:25:14 +08:00
										 |  |  |   /** | 
					
						
							| 
									
										
										
										
											2018-11-01 13:51:37 -05:00
										 |  |  |    * @description | 
					
						
							| 
									
										
										
										
											2018-02-01 11:25:14 +08:00
										 |  |  |    * The event name for control to update upon. | 
					
						
							|  |  |  |    */ | 
					
						
							|  |  |  |   updateOn?: 'change'|'blur'|'submit'; | 
					
						
							| 
									
										
										
										
											2016-06-13 11:27:04 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-02 18:10:10 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-25 15:01:04 -07:00
										 |  |  | function isOptionsObj( | 
					
						
							|  |  |  |     validatorOrOpts?: ValidatorFn | ValidatorFn[] | AbstractControlOptions | null): boolean { | 
					
						
							|  |  |  |   return validatorOrOpts != null && !Array.isArray(validatorOrOpts) && | 
					
						
							|  |  |  |       typeof validatorOrOpts === 'object'; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  | /** | 
					
						
							| 
									
										
										
										
											2018-04-05 10:58:12 +01:00
										 |  |  |  * This is the base class for `FormControl`, `FormGroup`, and `FormArray`. | 
					
						
							| 
									
										
										
										
											2016-09-12 20:31:13 -07:00
										 |  |  |  * | 
					
						
							|  |  |  |  * It provides some of the shared behavior that all controls and groups of controls have, like | 
					
						
							|  |  |  |  * running validators, calculating status, and resetting state. It also defines the properties | 
					
						
							|  |  |  |  * that are shared between all sub-classes, like `value`, `valid`, and `dirty`. It shouldn't be | 
					
						
							|  |  |  |  * instantiated directly. | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2018-02-08 15:00:53 +00:00
										 |  |  |  * @see [Forms Guide](/guide/forms) | 
					
						
							|  |  |  |  * @see [Reactive Forms Guide](/guide/reactive-forms) | 
					
						
							|  |  |  |  * @see [Dynamic Forms Guide](/guide/dynamic-form) | 
					
						
							| 
									
										
										
										
											2018-04-05 22:31:44 +01:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2018-10-19 17:36:24 +01:00
										 |  |  |  * @publicApi | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  |  */ | 
					
						
							|  |  |  | export abstract class AbstractControl { | 
					
						
							| 
									
										
										
										
											2017-08-07 15:39:25 -07:00
										 |  |  |   /** @internal */ | 
					
						
							| 
									
										
										
										
											2018-06-18 16:38:33 -07:00
										 |  |  |   // TODO(issue/24571): remove '!'.
 | 
					
						
							|  |  |  |   _pendingDirty !: boolean; | 
					
						
							| 
									
										
										
										
											2017-08-07 15:39:25 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |   /** @internal */ | 
					
						
							| 
									
										
										
										
											2018-06-18 16:38:33 -07:00
										 |  |  |   // TODO(issue/24571): remove '!'.
 | 
					
						
							|  |  |  |   _pendingTouched !: boolean; | 
					
						
							| 
									
										
										
										
											2017-08-07 15:39:25 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-02 15:57:35 -07:00
										 |  |  |   /** @internal */ | 
					
						
							|  |  |  |   _onCollectionChange = () => {}; | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-09 15:41:53 -07:00
										 |  |  |   /** @internal */ | 
					
						
							| 
									
										
										
										
											2018-06-18 16:38:33 -07:00
										 |  |  |   // TODO(issue/24571): remove '!'.
 | 
					
						
							|  |  |  |   _updateOn !: FormHooks; | 
					
						
							| 
									
										
										
										
											2017-08-09 15:41:53 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-06-18 16:38:33 -07:00
										 |  |  |   // TODO(issue/24571): remove '!'.
 | 
					
						
							|  |  |  |   private _parent !: FormGroup | FormArray; | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  |   private _asyncValidationSubscription: any; | 
					
						
							| 
									
										
										
										
											2018-06-07 13:31:25 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |   /** | 
					
						
							| 
									
										
										
										
											2018-06-11 14:24:00 -05:00
										 |  |  |    * The current value of the control. | 
					
						
							|  |  |  |    * | 
					
						
							|  |  |  |    * * For a `FormControl`, the current value. | 
					
						
							|  |  |  |    * * For a `FormGroup`, the values of enabled controls as an object | 
					
						
							|  |  |  |    * with a key-value pair for each member of the group. | 
					
						
							|  |  |  |    * * For a `FormArray`, the values of enabled controls as an array. | 
					
						
							| 
									
										
										
										
											2018-06-07 13:37:01 -05:00
										 |  |  |    * | 
					
						
							| 
									
										
										
										
											2018-06-07 13:31:25 -05:00
										 |  |  |    */ | 
					
						
							| 
									
										
										
										
											2017-09-13 14:00:10 -07:00
										 |  |  |   public readonly value: any; | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-08 15:00:53 +00:00
										 |  |  |   /** | 
					
						
							|  |  |  |    * Initialize the AbstractControl instance. | 
					
						
							| 
									
										
										
										
											2018-06-01 07:35:06 -05:00
										 |  |  |    * | 
					
						
							| 
									
										
										
										
											2018-06-11 14:24:00 -05:00
										 |  |  |    * @param validator The function that determines the synchronous validity of this control. | 
					
						
							|  |  |  |    * @param asyncValidator The function that determines the asynchronous validity of this | 
					
						
							| 
									
										
										
										
											2018-02-08 15:00:53 +00:00
										 |  |  |    * control. | 
					
						
							|  |  |  |    */ | 
					
						
							| 
									
										
										
										
											2017-04-17 11:13:30 -07:00
										 |  |  |   constructor(public validator: ValidatorFn|null, public asyncValidator: AsyncValidatorFn|null) {} | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-19 19:55:50 +03:00
										 |  |  |   /** | 
					
						
							|  |  |  |    * The parent control. | 
					
						
							|  |  |  |    */ | 
					
						
							|  |  |  |   get parent(): FormGroup|FormArray { return this._parent; } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-12 20:31:13 -07:00
										 |  |  |   /** | 
					
						
							|  |  |  |    * The validation status of the control. There are four possible | 
					
						
							| 
									
										
										
										
											2018-06-06 12:17:30 -05:00
										 |  |  |    * validation status values: | 
					
						
							| 
									
										
										
										
											2016-09-12 20:31:13 -07:00
										 |  |  |    * | 
					
						
							| 
									
										
										
										
											2018-06-06 12:17:30 -05:00
										 |  |  |    * * **VALID**: This control has passed all validation checks. | 
					
						
							|  |  |  |    * * **INVALID**: This control has failed at least one validation check. | 
					
						
							|  |  |  |    * * **PENDING**: This control is in the midst of conducting a validation check. | 
					
						
							|  |  |  |    * * **DISABLED**: This control is exempt from validation checks. | 
					
						
							| 
									
										
										
										
											2016-09-12 20:31:13 -07:00
										 |  |  |    * | 
					
						
							| 
									
										
										
										
											2018-06-06 12:17:30 -05:00
										 |  |  |    * These status values are mutually exclusive, so a control cannot be | 
					
						
							| 
									
										
										
										
											2016-09-12 20:31:13 -07:00
										 |  |  |    * both valid AND invalid or invalid AND disabled. | 
					
						
							|  |  |  |    */ | 
					
						
							| 
									
										
										
										
											2018-06-18 16:38:33 -07:00
										 |  |  |   // TODO(issue/24571): remove '!'.
 | 
					
						
							|  |  |  |   public readonly status !: string; | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-12 20:31:13 -07:00
										 |  |  |   /** | 
					
						
							| 
									
										
										
										
											2018-06-01 07:35:06 -05:00
										 |  |  |    * A control is `valid` when its `status` is `VALID`. | 
					
						
							| 
									
										
										
										
											2018-06-11 15:48:35 -05:00
										 |  |  |    * | 
					
						
							| 
									
										
										
										
											2019-01-11 11:16:54 +00:00
										 |  |  |    * @see {@link AbstractControl.status} | 
					
						
							| 
									
										
										
										
											2016-09-12 20:31:13 -07:00
										 |  |  |    * | 
					
						
							| 
									
										
										
										
											2018-06-11 14:24:00 -05:00
										 |  |  |    * @returns True if the control has passed all of its validation tests, | 
					
						
							| 
									
										
										
										
											2018-06-06 12:17:30 -05:00
										 |  |  |    * false otherwise. | 
					
						
							| 
									
										
										
										
											2016-09-12 20:31:13 -07:00
										 |  |  |    */ | 
					
						
							| 
									
										
										
										
											2017-09-13 14:00:10 -07:00
										 |  |  |   get valid(): boolean { return this.status === VALID; } | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-12 20:31:13 -07:00
										 |  |  |   /** | 
					
						
							| 
									
										
										
										
											2018-06-01 07:35:06 -05:00
										 |  |  |    * A control is `invalid` when its `status` is `INVALID`. | 
					
						
							| 
									
										
										
										
											2018-06-11 15:48:35 -05:00
										 |  |  |    * | 
					
						
							| 
									
										
										
										
											2019-01-11 11:16:54 +00:00
										 |  |  |    * @see {@link AbstractControl.status} | 
					
						
							| 
									
										
										
										
											2018-06-11 15:48:35 -05:00
										 |  |  |    * | 
					
						
							| 
									
										
										
										
											2018-06-11 14:24:00 -05:00
										 |  |  |    * @returns True if this control has failed one or more of its validation checks, | 
					
						
							| 
									
										
										
										
											2018-06-06 12:17:30 -05:00
										 |  |  |    * false otherwise. | 
					
						
							| 
									
										
										
										
											2016-09-12 20:31:13 -07:00
										 |  |  |    */ | 
					
						
							| 
									
										
										
										
											2017-09-13 14:00:10 -07:00
										 |  |  |   get invalid(): boolean { return this.status === INVALID; } | 
					
						
							| 
									
										
										
										
											2016-08-01 18:41:25 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  |   /** | 
					
						
							| 
									
										
										
										
											2018-06-01 07:35:06 -05:00
										 |  |  |    * A control is `pending` when its `status` is `PENDING`. | 
					
						
							| 
									
										
										
										
											2018-06-11 15:48:35 -05:00
										 |  |  |    * | 
					
						
							| 
									
										
										
										
											2019-01-11 11:16:54 +00:00
										 |  |  |    * @see {@link AbstractControl.status} | 
					
						
							| 
									
										
										
										
											2018-06-11 15:48:35 -05:00
										 |  |  |    * | 
					
						
							| 
									
										
										
										
											2018-06-11 14:24:00 -05:00
										 |  |  |    * @returns True if this control is in the process of conducting a validation check, | 
					
						
							| 
									
										
										
										
											2018-06-06 12:17:30 -05:00
										 |  |  |    * false otherwise. | 
					
						
							| 
									
										
										
										
											2016-09-12 20:31:13 -07:00
										 |  |  |    */ | 
					
						
							| 
									
										
										
										
											2017-09-13 14:00:10 -07:00
										 |  |  |   get pending(): boolean { return this.status == PENDING; } | 
					
						
							| 
									
										
										
										
											2016-09-12 20:31:13 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |   /** | 
					
						
							| 
									
										
										
										
											2018-06-01 07:35:06 -05:00
										 |  |  |    * A control is `disabled` when its `status` is `DISABLED`. | 
					
						
							| 
									
										
										
										
											2018-06-07 13:37:01 -05:00
										 |  |  |    * | 
					
						
							| 
									
										
										
										
											2016-09-12 20:31:13 -07:00
										 |  |  |    * Disabled controls are exempt from validation checks and | 
					
						
							|  |  |  |    * are not included in the aggregate value of their ancestor | 
					
						
							|  |  |  |    * controls. | 
					
						
							| 
									
										
										
										
											2018-06-11 14:24:00 -05:00
										 |  |  |    * | 
					
						
							| 
									
										
										
										
											2019-01-11 11:16:54 +00:00
										 |  |  |    * @see {@link AbstractControl.status} | 
					
						
							|  |  |  |    * | 
					
						
							| 
									
										
										
										
											2018-06-11 14:24:00 -05:00
										 |  |  |    * @returns True if the control is disabled, false otherwise. | 
					
						
							| 
									
										
										
										
											2016-09-12 20:31:13 -07:00
										 |  |  |    */ | 
					
						
							| 
									
										
										
										
											2017-09-13 14:00:10 -07:00
										 |  |  |   get disabled(): boolean { return this.status === DISABLED; } | 
					
						
							| 
									
										
										
										
											2016-09-12 20:31:13 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |   /** | 
					
						
							| 
									
										
										
										
											2018-06-01 07:35:06 -05:00
										 |  |  |    * A control is `enabled` as long as its `status` is not `DISABLED`. | 
					
						
							| 
									
										
										
										
											2018-06-11 15:48:35 -05:00
										 |  |  |    * | 
					
						
							| 
									
										
										
										
											2018-06-11 14:24:00 -05:00
										 |  |  |    * @returns True if the control has any status other than 'DISABLED', | 
					
						
							| 
									
										
										
										
											2018-06-06 12:17:30 -05:00
										 |  |  |    * false if the status is 'DISABLED'. | 
					
						
							| 
									
										
										
										
											2018-06-07 13:37:01 -05:00
										 |  |  |    * | 
					
						
							| 
									
										
										
										
											2019-01-11 11:16:54 +00:00
										 |  |  |    * @see {@link AbstractControl.status} | 
					
						
							|  |  |  |    * | 
					
						
							| 
									
										
										
										
											2016-09-12 20:31:13 -07:00
										 |  |  |    */ | 
					
						
							| 
									
										
										
										
											2017-09-13 14:00:10 -07:00
										 |  |  |   get enabled(): boolean { return this.status !== DISABLED; } | 
					
						
							| 
									
										
										
										
											2016-09-12 20:31:13 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |   /** | 
					
						
							| 
									
										
										
										
											2018-06-06 12:17:30 -05:00
										 |  |  |    * An object containing any errors generated by failing validation, | 
					
						
							|  |  |  |    * or null if there are no errors. | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  |    */ | 
					
						
							| 
									
										
										
										
											2018-06-18 16:38:33 -07:00
										 |  |  |   // TODO(issue/24571): remove '!'.
 | 
					
						
							|  |  |  |   public readonly errors !: ValidationErrors | null; | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-12 20:31:13 -07:00
										 |  |  |   /** | 
					
						
							|  |  |  |    * A control is `pristine` if the user has not yet changed | 
					
						
							|  |  |  |    * the value in the UI. | 
					
						
							|  |  |  |    * | 
					
						
							| 
									
										
										
										
											2018-06-11 14:24:00 -05:00
										 |  |  |    * @returns True if the user has not yet changed the value in the UI; compare `dirty`. | 
					
						
							| 
									
										
										
										
											2018-06-06 12:17:30 -05:00
										 |  |  |    * Programmatic changes to a control's value do not mark it dirty. | 
					
						
							| 
									
										
										
										
											2016-09-12 20:31:13 -07:00
										 |  |  |    */ | 
					
						
							| 
									
										
										
										
											2017-09-13 14:00:10 -07:00
										 |  |  |   public readonly pristine: boolean = true; | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-12 20:31:13 -07:00
										 |  |  |   /** | 
					
						
							|  |  |  |    * A control is `dirty` if the user has changed the value | 
					
						
							|  |  |  |    * in the UI. | 
					
						
							|  |  |  |    * | 
					
						
							| 
									
										
										
										
											2018-06-11 14:24:00 -05:00
										 |  |  |    * @returns True if the user has changed the value of this control in the UI; compare `pristine`. | 
					
						
							| 
									
										
										
										
											2018-06-06 12:17:30 -05:00
										 |  |  |    * Programmatic changes to a control's value do not mark it dirty. | 
					
						
							| 
									
										
										
										
											2016-09-12 20:31:13 -07:00
										 |  |  |    */ | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  |   get dirty(): boolean { return !this.pristine; } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-12 20:31:13 -07:00
										 |  |  |   /** | 
					
						
							| 
									
										
										
										
											2018-06-11 14:24:00 -05:00
										 |  |  |    * True if the control is marked as `touched`. | 
					
						
							|  |  |  |    * | 
					
						
							| 
									
										
										
										
											2018-06-01 07:35:06 -05:00
										 |  |  |    * A control is marked `touched` once the user has triggered | 
					
						
							|  |  |  |    * a `blur` event on it. | 
					
						
							|  |  |  |    */ | 
					
						
							| 
									
										
										
										
											2017-09-13 14:00:10 -07:00
										 |  |  |   public readonly touched: boolean = false; | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-12 20:31:13 -07:00
										 |  |  |   /** | 
					
						
							| 
									
										
										
										
											2018-06-11 14:24:00 -05:00
										 |  |  |    * True if the control has not been marked as touched | 
					
						
							|  |  |  |    * | 
					
						
							| 
									
										
										
										
											2016-09-12 20:31:13 -07:00
										 |  |  |    * A control is `untouched` if the user has not yet triggered | 
					
						
							|  |  |  |    * a `blur` event on it. | 
					
						
							|  |  |  |    */ | 
					
						
							| 
									
										
										
										
											2017-09-13 14:00:10 -07:00
										 |  |  |   get untouched(): boolean { return !this.touched; } | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-12 20:31:13 -07:00
										 |  |  |   /** | 
					
						
							| 
									
										
										
										
											2018-06-11 14:24:00 -05:00
										 |  |  |    * A multicasting observable that emits an event every time the value of the control changes, in | 
					
						
							| 
									
										
										
										
											2016-09-12 20:31:13 -07:00
										 |  |  |    * the UI or programmatically. | 
					
						
							|  |  |  |    */ | 
					
						
							| 
									
										
										
										
											2018-06-18 16:38:33 -07:00
										 |  |  |   // TODO(issue/24571): remove '!'.
 | 
					
						
							|  |  |  |   public readonly valueChanges !: Observable<any>; | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-12 20:31:13 -07:00
										 |  |  |   /** | 
					
						
							| 
									
										
										
										
											2018-06-11 14:24:00 -05:00
										 |  |  |    * A multicasting observable that emits an event every time the validation `status` of the control | 
					
						
							|  |  |  |    * recalculates. | 
					
						
							| 
									
										
										
										
											2019-01-11 11:16:54 +00:00
										 |  |  |    * | 
					
						
							|  |  |  |    * @see {@link AbstractControl.status} | 
					
						
							|  |  |  |    * | 
					
						
							| 
									
										
										
										
											2016-09-12 20:31:13 -07:00
										 |  |  |    */ | 
					
						
							| 
									
										
										
										
											2018-06-18 16:38:33 -07:00
										 |  |  |   // TODO(issue/24571): remove '!'.
 | 
					
						
							|  |  |  |   public readonly statusChanges !: Observable<any>; | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-09 15:41:53 -07:00
										 |  |  |   /** | 
					
						
							| 
									
										
										
										
											2018-06-11 14:24:00 -05:00
										 |  |  |    * Reports the update strategy of the `AbstractControl` (meaning | 
					
						
							|  |  |  |    * the event on which the control updates itself). | 
					
						
							| 
									
										
										
										
											2018-06-01 07:35:06 -05:00
										 |  |  |    * Possible values: `'change'` | `'blur'` | `'submit'` | 
					
						
							|  |  |  |    * Default value: `'change'` | 
					
						
							| 
									
										
										
										
											2017-08-09 15:41:53 -07:00
										 |  |  |    */ | 
					
						
							|  |  |  |   get updateOn(): FormHooks { | 
					
						
							|  |  |  |     return this._updateOn ? this._updateOn : (this.parent ? this.parent.updateOn : 'change'); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-12 20:31:13 -07:00
										 |  |  |   /** | 
					
						
							|  |  |  |    * Sets the synchronous validators that are active on this control.  Calling | 
					
						
							| 
									
										
										
										
											2018-06-11 14:24:00 -05:00
										 |  |  |    * this overwrites any existing sync validators. | 
					
						
							| 
									
										
										
										
											2016-09-12 20:31:13 -07:00
										 |  |  |    */ | 
					
						
							| 
									
										
										
										
											2017-04-17 11:13:30 -07:00
										 |  |  |   setValidators(newValidator: ValidatorFn|ValidatorFn[]|null): void { | 
					
						
							| 
									
										
										
										
											2016-09-12 20:31:13 -07:00
										 |  |  |     this.validator = coerceToValidator(newValidator); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2016-08-24 16:58:43 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-12 20:31:13 -07:00
										 |  |  |   /** | 
					
						
							|  |  |  |    * Sets the async validators that are active on this control. Calling this | 
					
						
							| 
									
										
										
										
											2018-06-11 14:24:00 -05:00
										 |  |  |    * overwrites any existing async validators. | 
					
						
							| 
									
										
										
										
											2016-09-12 20:31:13 -07:00
										 |  |  |    */ | 
					
						
							| 
									
										
										
										
											2017-11-10 21:09:22 +13:00
										 |  |  |   setAsyncValidators(newValidator: AsyncValidatorFn|AsyncValidatorFn[]|null): void { | 
					
						
							| 
									
										
										
										
											2016-06-23 11:18:07 -04:00
										 |  |  |     this.asyncValidator = coerceToAsyncValidator(newValidator); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-12 20:31:13 -07:00
										 |  |  |   /** | 
					
						
							|  |  |  |    * Empties out the sync validator list. | 
					
						
							|  |  |  |    */ | 
					
						
							| 
									
										
										
										
											2016-06-23 11:18:07 -04:00
										 |  |  |   clearValidators(): void { this.validator = null; } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-12 20:31:13 -07:00
										 |  |  |   /** | 
					
						
							|  |  |  |    * Empties out the async validator list. | 
					
						
							|  |  |  |    */ | 
					
						
							|  |  |  |   clearAsyncValidators(): void { this.asyncValidator = null; } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /** | 
					
						
							| 
									
										
										
										
											2018-06-07 13:31:25 -05:00
										 |  |  |    * Marks the control as `touched`. A control is touched by focus and | 
					
						
							| 
									
										
										
										
											2019-01-11 11:16:54 +00:00
										 |  |  |    * blur events that do not change the value. | 
					
						
							|  |  |  |    * | 
					
						
							|  |  |  |    * @see `markAsUntouched()` | 
					
						
							|  |  |  |    * @see `markAsDirty()` | 
					
						
							|  |  |  |    * @see `markAsPristine()` | 
					
						
							| 
									
										
										
										
											2016-09-12 20:31:13 -07:00
										 |  |  |    * | 
					
						
							| 
									
										
										
										
											2019-01-11 11:16:54 +00:00
										 |  |  |    * @param opts Configuration options that determine how the control propagates changes | 
					
						
							| 
									
										
										
										
											2018-06-11 15:48:35 -05:00
										 |  |  |    * and emits events events after marking is applied. | 
					
						
							| 
									
										
										
										
											2018-06-06 12:17:30 -05:00
										 |  |  |    * * `onlySelf`: When true, mark only this control. When false or not supplied, | 
					
						
							| 
									
										
										
										
											2018-06-11 15:48:35 -05:00
										 |  |  |    * marks all direct ancestors. Default is false. | 
					
						
							| 
									
										
										
										
											2016-09-12 20:31:13 -07:00
										 |  |  |    */ | 
					
						
							| 
									
										
										
										
											2017-06-12 10:59:29 -07:00
										 |  |  |   markAsTouched(opts: {onlySelf?: boolean} = {}): void { | 
					
						
							| 
									
										
										
										
											2017-09-13 14:00:10 -07:00
										 |  |  |     (this as{touched: boolean}).touched = true; | 
					
						
							| 
									
										
										
										
											2016-07-01 15:36:04 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-06-12 10:59:29 -07:00
										 |  |  |     if (this._parent && !opts.onlySelf) { | 
					
						
							|  |  |  |       this._parent.markAsTouched(opts); | 
					
						
							| 
									
										
										
										
											2016-07-01 15:36:04 -07:00
										 |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-29 09:36:17 +01:00
										 |  |  |   /** | 
					
						
							|  |  |  |    * Marks the control and all its descendant controls as `touched`. | 
					
						
							|  |  |  |    * @see `markAsTouched()` | 
					
						
							|  |  |  |    */ | 
					
						
							|  |  |  |   markAllAsTouched(): void { | 
					
						
							|  |  |  |     this.markAsTouched({onlySelf: true}); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     this._forEachChild((control: AbstractControl) => control.markAllAsTouched()); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-12 20:31:13 -07:00
										 |  |  |   /** | 
					
						
							|  |  |  |    * Marks the control as `untouched`. | 
					
						
							|  |  |  |    * | 
					
						
							| 
									
										
										
										
											2018-06-11 14:24:00 -05:00
										 |  |  |    * If the control has any children, also marks all children as `untouched` | 
					
						
							|  |  |  |    * and recalculates the `touched` status of all parent controls. | 
					
						
							| 
									
										
										
										
											2018-06-01 07:35:06 -05:00
										 |  |  |    * | 
					
						
							| 
									
										
										
										
											2019-01-11 11:16:54 +00:00
										 |  |  |    * @see `markAsTouched()` | 
					
						
							|  |  |  |    * @see `markAsDirty()` | 
					
						
							|  |  |  |    * @see `markAsPristine()` | 
					
						
							|  |  |  |    * | 
					
						
							|  |  |  |    * @param opts Configuration options that determine how the control propagates changes | 
					
						
							| 
									
										
										
										
											2018-06-11 15:48:35 -05:00
										 |  |  |    * and emits events after the marking is applied. | 
					
						
							| 
									
										
										
										
											2018-06-06 12:17:30 -05:00
										 |  |  |    * * `onlySelf`: When true, mark only this control. When false or not supplied, | 
					
						
							| 
									
										
										
										
											2018-06-11 15:48:35 -05:00
										 |  |  |    * marks all direct ancestors. Default is false. | 
					
						
							| 
									
										
										
										
											2016-09-12 20:31:13 -07:00
										 |  |  |    */ | 
					
						
							| 
									
										
										
										
											2017-06-12 10:59:29 -07:00
										 |  |  |   markAsUntouched(opts: {onlySelf?: boolean} = {}): void { | 
					
						
							| 
									
										
										
										
											2017-09-13 14:00:10 -07:00
										 |  |  |     (this as{touched: boolean}).touched = false; | 
					
						
							| 
									
										
										
										
											2017-08-07 15:39:25 -07:00
										 |  |  |     this._pendingTouched = false; | 
					
						
							| 
									
										
										
										
											2016-09-12 20:31:13 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |     this._forEachChild( | 
					
						
							|  |  |  |         (control: AbstractControl) => { control.markAsUntouched({onlySelf: true}); }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-06-12 10:59:29 -07:00
										 |  |  |     if (this._parent && !opts.onlySelf) { | 
					
						
							|  |  |  |       this._parent._updateTouched(opts); | 
					
						
							| 
									
										
										
										
											2016-09-12 20:31:13 -07:00
										 |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /** | 
					
						
							| 
									
										
										
										
											2018-06-11 14:24:00 -05:00
										 |  |  |    * Marks the control as `dirty`. A control becomes dirty when | 
					
						
							| 
									
										
										
										
											2018-11-19 14:45:47 -05:00
										 |  |  |    * the control's value is changed through the UI; compare `markAsTouched`. | 
					
						
							| 
									
										
										
										
											2016-09-12 20:31:13 -07:00
										 |  |  |    * | 
					
						
							| 
									
										
										
										
											2019-01-11 11:16:54 +00:00
										 |  |  |    * @see `markAsTouched()` | 
					
						
							|  |  |  |    * @see `markAsUntouched()` | 
					
						
							|  |  |  |    * @see `markAsPristine()` | 
					
						
							|  |  |  |    * | 
					
						
							|  |  |  |    * @param opts Configuration options that determine how the control propagates changes | 
					
						
							| 
									
										
										
										
											2018-06-11 15:48:35 -05:00
										 |  |  |    * and emits events after marking is applied. | 
					
						
							| 
									
										
										
										
											2018-06-06 12:17:30 -05:00
										 |  |  |    * * `onlySelf`: When true, mark only this control. When false or not supplied, | 
					
						
							| 
									
										
										
										
											2018-06-11 15:48:35 -05:00
										 |  |  |    * marks all direct ancestors. Default is false. | 
					
						
							| 
									
										
										
										
											2016-09-12 20:31:13 -07:00
										 |  |  |    */ | 
					
						
							| 
									
										
										
										
											2017-06-12 10:59:29 -07:00
										 |  |  |   markAsDirty(opts: {onlySelf?: boolean} = {}): void { | 
					
						
							| 
									
										
										
										
											2017-09-13 14:00:10 -07:00
										 |  |  |     (this as{pristine: boolean}).pristine = false; | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-06-12 10:59:29 -07:00
										 |  |  |     if (this._parent && !opts.onlySelf) { | 
					
						
							|  |  |  |       this._parent.markAsDirty(opts); | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-12 20:31:13 -07:00
										 |  |  |   /** | 
					
						
							|  |  |  |    * Marks the control as `pristine`. | 
					
						
							|  |  |  |    * | 
					
						
							| 
									
										
										
										
											2018-06-11 14:24:00 -05:00
										 |  |  |    * If the control has any children, marks all children as `pristine`, | 
					
						
							|  |  |  |    * and recalculates the `pristine` status of all parent | 
					
						
							| 
									
										
										
										
											2016-09-12 20:31:13 -07:00
										 |  |  |    * controls. | 
					
						
							| 
									
										
										
										
											2018-06-01 07:35:06 -05:00
										 |  |  |    * | 
					
						
							| 
									
										
										
										
											2019-01-11 11:16:54 +00:00
										 |  |  |    * @see `markAsTouched()` | 
					
						
							|  |  |  |    * @see `markAsUntouched()` | 
					
						
							|  |  |  |    * @see `markAsDirty()` | 
					
						
							|  |  |  |    * | 
					
						
							|  |  |  |    * @param opts Configuration options that determine how the control emits events after | 
					
						
							| 
									
										
										
										
											2018-06-11 14:24:00 -05:00
										 |  |  |    * marking is applied. | 
					
						
							| 
									
										
										
										
											2018-06-06 12:17:30 -05:00
										 |  |  |    * * `onlySelf`: When true, mark only this control. When false or not supplied, | 
					
						
							| 
									
										
										
										
											2018-06-11 15:48:35 -05:00
										 |  |  |    * marks all direct ancestors. Default is false.. | 
					
						
							| 
									
										
										
										
											2016-09-12 20:31:13 -07:00
										 |  |  |    */ | 
					
						
							| 
									
										
										
										
											2017-06-12 10:59:29 -07:00
										 |  |  |   markAsPristine(opts: {onlySelf?: boolean} = {}): void { | 
					
						
							| 
									
										
										
										
											2017-09-13 14:00:10 -07:00
										 |  |  |     (this as{pristine: boolean}).pristine = true; | 
					
						
							| 
									
										
										
										
											2017-08-07 15:39:25 -07:00
										 |  |  |     this._pendingDirty = false; | 
					
						
							| 
									
										
										
										
											2016-07-12 15:02:25 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |     this._forEachChild((control: AbstractControl) => { control.markAsPristine({onlySelf: true}); }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-06-12 10:59:29 -07:00
										 |  |  |     if (this._parent && !opts.onlySelf) { | 
					
						
							|  |  |  |       this._parent._updatePristine(opts); | 
					
						
							| 
									
										
										
										
											2016-07-12 15:02:25 -07:00
										 |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-12 20:31:13 -07:00
										 |  |  |   /** | 
					
						
							|  |  |  |    * Marks the control as `pending`. | 
					
						
							| 
									
										
										
										
											2017-11-06 21:59:09 +13:00
										 |  |  |    * | 
					
						
							| 
									
										
										
										
											2018-06-11 14:24:00 -05:00
										 |  |  |    * A control is pending while the control performs async validation. | 
					
						
							| 
									
										
										
										
											2017-11-06 21:59:09 +13:00
										 |  |  |    * | 
					
						
							| 
									
										
										
										
											2019-01-11 11:16:54 +00:00
										 |  |  |    * @see {@link AbstractControl.status} | 
					
						
							|  |  |  |    * | 
					
						
							|  |  |  |    * @param opts Configuration options that determine how the control propagates changes and | 
					
						
							| 
									
										
										
										
											2018-06-11 14:24:00 -05:00
										 |  |  |    * emits events after marking is applied. | 
					
						
							| 
									
										
										
										
											2018-06-06 12:17:30 -05:00
										 |  |  |    * * `onlySelf`: When true, mark only this control. When false or not supplied, | 
					
						
							| 
									
										
										
										
											2018-06-11 15:48:35 -05:00
										 |  |  |    * marks all direct ancestors. Default is false.. | 
					
						
							|  |  |  |    * * `emitEvent`: When true or not supplied (the default), the `statusChanges` | 
					
						
							|  |  |  |    * observable emits an event with the latest status the control is marked pending. | 
					
						
							|  |  |  |    * When false, no events are emitted. | 
					
						
							| 
									
										
										
										
											2018-06-07 13:37:01 -05:00
										 |  |  |    * | 
					
						
							| 
									
										
										
										
											2016-09-12 20:31:13 -07:00
										 |  |  |    */ | 
					
						
							| 
									
										
										
										
											2017-11-06 21:59:09 +13:00
										 |  |  |   markAsPending(opts: {onlySelf?: boolean, emitEvent?: boolean} = {}): void { | 
					
						
							| 
									
										
										
										
											2017-09-13 14:00:10 -07:00
										 |  |  |     (this as{status: string}).status = PENDING; | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-06 21:59:09 +13:00
										 |  |  |     if (opts.emitEvent !== false) { | 
					
						
							|  |  |  |       (this.statusChanges as EventEmitter<any>).emit(this.status); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-06-12 10:59:29 -07:00
										 |  |  |     if (this._parent && !opts.onlySelf) { | 
					
						
							|  |  |  |       this._parent.markAsPending(opts); | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-12 20:31:13 -07:00
										 |  |  |   /** | 
					
						
							| 
									
										
										
										
											2018-06-11 14:24:00 -05:00
										 |  |  |    * Disables the control. This means the control is exempt from validation checks and | 
					
						
							| 
									
										
										
										
											2016-09-12 20:31:13 -07:00
										 |  |  |    * excluded from the aggregate value of any parent. Its status is `DISABLED`. | 
					
						
							|  |  |  |    * | 
					
						
							| 
									
										
										
										
											2018-06-11 14:24:00 -05:00
										 |  |  |    * If the control has children, all children are also disabled. | 
					
						
							| 
									
										
										
										
											2018-06-01 07:35:06 -05:00
										 |  |  |    * | 
					
						
							| 
									
										
										
										
											2019-01-11 11:16:54 +00:00
										 |  |  |    * @see {@link AbstractControl.status} | 
					
						
							|  |  |  |    * | 
					
						
							|  |  |  |    * @param opts Configuration options that determine how the control propagates | 
					
						
							| 
									
										
										
										
											2018-06-11 14:24:00 -05:00
										 |  |  |    * changes and emits events after the control is disabled. | 
					
						
							| 
									
										
										
										
											2018-06-06 12:17:30 -05:00
										 |  |  |    * * `onlySelf`: When true, mark only this control. When false or not supplied, | 
					
						
							| 
									
										
										
										
											2018-06-11 15:48:35 -05:00
										 |  |  |    * marks all direct ancestors. Default is false.. | 
					
						
							|  |  |  |    * * `emitEvent`: When true or not supplied (the default), both the `statusChanges` and | 
					
						
							|  |  |  |    * `valueChanges` | 
					
						
							|  |  |  |    * observables emit events with the latest status and value when the control is disabled. | 
					
						
							|  |  |  |    * When false, no events are emitted. | 
					
						
							| 
									
										
										
										
											2016-09-12 20:31:13 -07:00
										 |  |  |    */ | 
					
						
							| 
									
										
										
										
											2017-06-12 10:59:29 -07:00
										 |  |  |   disable(opts: {onlySelf?: boolean, emitEvent?: boolean} = {}): void { | 
					
						
							| 
									
										
										
										
											2018-06-20 17:16:42 +02:00
										 |  |  |     // If parent has been marked artificially dirty we don't want to re-calculate the
 | 
					
						
							|  |  |  |     // parent's dirtiness based on the children.
 | 
					
						
							|  |  |  |     const skipPristineCheck = this._parentMarkedDirty(opts.onlySelf); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-09-13 14:00:10 -07:00
										 |  |  |     (this as{status: string}).status = DISABLED; | 
					
						
							|  |  |  |     (this as{errors: ValidationErrors | null}).errors = null; | 
					
						
							| 
									
										
										
										
											2017-12-14 16:51:05 +01:00
										 |  |  |     this._forEachChild( | 
					
						
							|  |  |  |         (control: AbstractControl) => { control.disable({...opts, onlySelf: true}); }); | 
					
						
							| 
									
										
										
										
											2016-08-24 16:58:43 -07:00
										 |  |  |     this._updateValue(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-06-12 10:59:29 -07:00
										 |  |  |     if (opts.emitEvent !== false) { | 
					
						
							| 
									
										
										
										
											2017-09-13 14:00:10 -07:00
										 |  |  |       (this.valueChanges as EventEmitter<any>).emit(this.value); | 
					
						
							|  |  |  |       (this.statusChanges as EventEmitter<string>).emit(this.status); | 
					
						
							| 
									
										
										
										
											2016-08-24 16:58:43 -07:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-06-20 17:16:42 +02:00
										 |  |  |     this._updateAncestors({...opts, skipPristineCheck}); | 
					
						
							| 
									
										
										
										
											2016-09-20 09:08:12 -07:00
										 |  |  |     this._onDisabledChange.forEach((changeFn) => changeFn(true)); | 
					
						
							| 
									
										
										
										
											2016-08-24 16:58:43 -07:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-12 20:31:13 -07:00
										 |  |  |   /** | 
					
						
							| 
									
										
										
										
											2018-06-11 14:24:00 -05:00
										 |  |  |    * Enables the control. This means the control is included in validation checks and | 
					
						
							|  |  |  |    * the aggregate value of its parent. Its status recalculates based on its value and | 
					
						
							| 
									
										
										
										
											2016-09-12 20:31:13 -07:00
										 |  |  |    * its validators. | 
					
						
							|  |  |  |    * | 
					
						
							| 
									
										
										
										
											2018-06-11 14:24:00 -05:00
										 |  |  |    * By default, if the control has children, all children are enabled. | 
					
						
							| 
									
										
										
										
											2018-06-01 07:35:06 -05:00
										 |  |  |    * | 
					
						
							| 
									
										
										
										
											2019-01-11 11:16:54 +00:00
										 |  |  |    * @see {@link AbstractControl.status} | 
					
						
							|  |  |  |    * | 
					
						
							|  |  |  |    * @param opts Configure options that control how the control propagates changes and | 
					
						
							| 
									
										
										
										
											2018-06-11 14:24:00 -05:00
										 |  |  |    * emits events when marked as untouched | 
					
						
							| 
									
										
										
										
											2018-06-06 12:17:30 -05:00
										 |  |  |    * * `onlySelf`: When true, mark only this control. When false or not supplied, | 
					
						
							| 
									
										
										
										
											2018-06-11 15:48:35 -05:00
										 |  |  |    * marks all direct ancestors. Default is false.. | 
					
						
							|  |  |  |    * * `emitEvent`: When true or not supplied (the default), both the `statusChanges` and | 
					
						
							|  |  |  |    * `valueChanges` | 
					
						
							|  |  |  |    * observables emit events with the latest status and value when the control is enabled. | 
					
						
							|  |  |  |    * When false, no events are emitted. | 
					
						
							| 
									
										
										
										
											2016-09-12 20:31:13 -07:00
										 |  |  |    */ | 
					
						
							| 
									
										
										
										
											2017-06-12 10:59:29 -07:00
										 |  |  |   enable(opts: {onlySelf?: boolean, emitEvent?: boolean} = {}): void { | 
					
						
							| 
									
										
										
										
											2018-06-20 17:16:42 +02:00
										 |  |  |     // If parent has been marked artificially dirty we don't want to re-calculate the
 | 
					
						
							|  |  |  |     // parent's dirtiness based on the children.
 | 
					
						
							|  |  |  |     const skipPristineCheck = this._parentMarkedDirty(opts.onlySelf); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-09-13 14:00:10 -07:00
										 |  |  |     (this as{status: string}).status = VALID; | 
					
						
							| 
									
										
										
										
											2017-12-14 16:51:05 +01:00
										 |  |  |     this._forEachChild( | 
					
						
							|  |  |  |         (control: AbstractControl) => { control.enable({...opts, onlySelf: true}); }); | 
					
						
							| 
									
										
										
										
											2017-06-12 10:59:29 -07:00
										 |  |  |     this.updateValueAndValidity({onlySelf: true, emitEvent: opts.emitEvent}); | 
					
						
							| 
									
										
										
										
											2016-08-24 16:58:43 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-06-20 17:16:42 +02:00
										 |  |  |     this._updateAncestors({...opts, skipPristineCheck}); | 
					
						
							| 
									
										
										
										
											2016-09-20 09:08:12 -07:00
										 |  |  |     this._onDisabledChange.forEach((changeFn) => changeFn(false)); | 
					
						
							| 
									
										
										
										
											2016-08-24 16:58:43 -07:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-06-20 17:16:42 +02:00
										 |  |  |   private _updateAncestors( | 
					
						
							|  |  |  |       opts: {onlySelf?: boolean, emitEvent?: boolean, skipPristineCheck?: boolean}) { | 
					
						
							| 
									
										
										
										
											2017-12-14 16:51:05 +01:00
										 |  |  |     if (this._parent && !opts.onlySelf) { | 
					
						
							|  |  |  |       this._parent.updateValueAndValidity(opts); | 
					
						
							| 
									
										
										
										
											2018-06-20 17:16:42 +02:00
										 |  |  |       if (!opts.skipPristineCheck) { | 
					
						
							|  |  |  |         this._parent._updatePristine(); | 
					
						
							|  |  |  |       } | 
					
						
							| 
									
										
										
										
											2016-08-24 16:58:43 -07:00
										 |  |  |       this._parent._updateTouched(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-06-01 07:35:06 -05:00
										 |  |  |   /** | 
					
						
							|  |  |  |    * @param parent Sets the parent of the control | 
					
						
							|  |  |  |    */ | 
					
						
							| 
									
										
										
										
											2016-06-10 11:15:59 -07:00
										 |  |  |   setParent(parent: FormGroup|FormArray): void { this._parent = parent; } | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-12 20:31:13 -07:00
										 |  |  |   /** | 
					
						
							|  |  |  |    * Sets the value of the control. Abstract method (implemented in sub-classes). | 
					
						
							|  |  |  |    */ | 
					
						
							| 
									
										
										
										
											2016-08-05 13:35:17 -07:00
										 |  |  |   abstract setValue(value: any, options?: Object): void; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-12 20:31:13 -07:00
										 |  |  |   /** | 
					
						
							|  |  |  |    * Patches the value of the control. Abstract method (implemented in sub-classes). | 
					
						
							|  |  |  |    */ | 
					
						
							| 
									
										
										
										
											2016-08-05 13:35:17 -07:00
										 |  |  |   abstract patchValue(value: any, options?: Object): void; | 
					
						
							| 
									
										
										
										
											2016-07-08 13:04:25 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-12 20:31:13 -07:00
										 |  |  |   /** | 
					
						
							|  |  |  |    * Resets the control. Abstract method (implemented in sub-classes). | 
					
						
							|  |  |  |    */ | 
					
						
							| 
									
										
										
										
											2016-07-12 15:02:25 -07:00
										 |  |  |   abstract reset(value?: any, options?: Object): void; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-12 20:31:13 -07:00
										 |  |  |   /** | 
					
						
							| 
									
										
										
										
											2018-06-11 14:24:00 -05:00
										 |  |  |    * Recalculates the value and validation status of the control. | 
					
						
							| 
									
										
										
										
											2016-09-12 20:31:13 -07:00
										 |  |  |    * | 
					
						
							| 
									
										
										
										
											2018-06-11 14:24:00 -05:00
										 |  |  |    * By default, it also updates the value and validity of its ancestors. | 
					
						
							| 
									
										
										
										
											2018-06-01 07:35:06 -05:00
										 |  |  |    * | 
					
						
							| 
									
										
										
										
											2018-06-11 15:48:35 -05:00
										 |  |  |    * @param opts Configuration options determine how the control propagates changes and emits events | 
					
						
							|  |  |  |    * after updates and validity checks are applied. | 
					
						
							| 
									
										
										
										
											2018-06-06 12:17:30 -05:00
										 |  |  |    * * `onlySelf`: When true, only update this control. When false or not supplied, | 
					
						
							| 
									
										
										
										
											2018-06-11 15:48:35 -05:00
										 |  |  |    * update all direct ancestors. Default is false.. | 
					
						
							|  |  |  |    * * `emitEvent`: When true or not supplied (the default), both the `statusChanges` and | 
					
						
							|  |  |  |    * `valueChanges` | 
					
						
							|  |  |  |    * observables emit events with the latest status and value when the control is updated. | 
					
						
							|  |  |  |    * When false, no events are emitted. | 
					
						
							| 
									
										
										
										
											2016-09-12 20:31:13 -07:00
										 |  |  |    */ | 
					
						
							| 
									
										
										
										
											2017-06-12 10:59:29 -07:00
										 |  |  |   updateValueAndValidity(opts: {onlySelf?: boolean, emitEvent?: boolean} = {}): void { | 
					
						
							| 
									
										
										
										
											2016-09-09 12:00:38 -07:00
										 |  |  |     this._setInitialStatus(); | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  |     this._updateValue(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-09 12:00:38 -07:00
										 |  |  |     if (this.enabled) { | 
					
						
							| 
									
										
										
										
											2016-12-04 01:17:09 +03:00
										 |  |  |       this._cancelExistingSubscription(); | 
					
						
							| 
									
										
										
										
											2017-09-13 14:00:10 -07:00
										 |  |  |       (this as{errors: ValidationErrors | null}).errors = this._runValidator(); | 
					
						
							|  |  |  |       (this as{status: string}).status = this._calculateStatus(); | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-09-13 14:00:10 -07:00
										 |  |  |       if (this.status === VALID || this.status === PENDING) { | 
					
						
							| 
									
										
										
										
											2017-06-12 10:59:29 -07:00
										 |  |  |         this._runAsyncValidator(opts.emitEvent); | 
					
						
							| 
									
										
										
										
											2016-09-09 12:00:38 -07:00
										 |  |  |       } | 
					
						
							| 
									
										
										
										
											2016-08-24 16:58:43 -07:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-06-12 10:59:29 -07:00
										 |  |  |     if (opts.emitEvent !== false) { | 
					
						
							| 
									
										
										
										
											2017-09-13 14:00:10 -07:00
										 |  |  |       (this.valueChanges as EventEmitter<any>).emit(this.value); | 
					
						
							|  |  |  |       (this.statusChanges as EventEmitter<string>).emit(this.status); | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-06-12 10:59:29 -07:00
										 |  |  |     if (this._parent && !opts.onlySelf) { | 
					
						
							|  |  |  |       this._parent.updateValueAndValidity(opts); | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-29 11:33:49 -07:00
										 |  |  |   /** @internal */ | 
					
						
							| 
									
										
										
										
											2017-06-12 10:59:29 -07:00
										 |  |  |   _updateTreeValidity(opts: {emitEvent?: boolean} = {emitEvent: true}) { | 
					
						
							|  |  |  |     this._forEachChild((ctrl: AbstractControl) => ctrl._updateTreeValidity(opts)); | 
					
						
							|  |  |  |     this.updateValueAndValidity({onlySelf: true, emitEvent: opts.emitEvent}); | 
					
						
							| 
									
										
										
										
											2016-08-29 11:33:49 -07:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-09-13 14:00:10 -07:00
										 |  |  |   private _setInitialStatus() { | 
					
						
							|  |  |  |     (this as{status: string}).status = this._allControlsDisabled() ? DISABLED : VALID; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2016-09-09 12:00:38 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-23 20:53:29 +03:00
										 |  |  |   private _runValidator(): ValidationErrors|null { | 
					
						
							| 
									
										
										
										
											2016-10-21 15:14:44 -07:00
										 |  |  |     return this.validator ? this.validator(this) : null; | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-04-17 11:13:30 -07:00
										 |  |  |   private _runAsyncValidator(emitEvent?: boolean): void { | 
					
						
							| 
									
										
										
										
											2016-10-21 15:14:44 -07:00
										 |  |  |     if (this.asyncValidator) { | 
					
						
							| 
									
										
										
										
											2017-09-13 14:00:10 -07:00
										 |  |  |       (this as{status: string}).status = PENDING; | 
					
						
							| 
									
										
										
										
											2016-10-21 15:14:44 -07:00
										 |  |  |       const obs = toObservable(this.asyncValidator(this)); | 
					
						
							| 
									
										
										
										
											2016-10-19 18:54:54 +02:00
										 |  |  |       this._asyncValidationSubscription = | 
					
						
							| 
									
										
										
										
											2017-02-23 20:53:29 +03:00
										 |  |  |           obs.subscribe((errors: ValidationErrors | null) => this.setErrors(errors, {emitEvent})); | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   private _cancelExistingSubscription(): void { | 
					
						
							| 
									
										
										
										
											2016-10-21 15:14:44 -07:00
										 |  |  |     if (this._asyncValidationSubscription) { | 
					
						
							| 
									
										
										
										
											2016-08-02 15:53:34 -07:00
										 |  |  |       this._asyncValidationSubscription.unsubscribe(); | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /** | 
					
						
							| 
									
										
										
										
											2018-06-11 14:24:00 -05:00
										 |  |  |    * Sets errors on a form control when running validations manually, rather than automatically. | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  |    * | 
					
						
							| 
									
										
										
										
											2018-06-11 14:24:00 -05:00
										 |  |  |    * Calling `setErrors` also updates the validity of the parent control. | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  |    * | 
					
						
							| 
									
										
										
										
											2018-09-20 15:18:14 +01:00
										 |  |  |    * @usageNotes | 
					
						
							| 
									
										
										
										
											2018-06-01 07:35:06 -05:00
										 |  |  |    * ### Manually set the errors for a control | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  |    * | 
					
						
							|  |  |  |    * ```
 | 
					
						
							| 
									
										
										
										
											2018-06-01 07:35:06 -05:00
										 |  |  |    * const login = new FormControl('someLogin'); | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  |    * login.setErrors({ | 
					
						
							| 
									
										
										
										
											2018-06-01 07:35:06 -05:00
										 |  |  |    *   notUnique: true | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  |    * }); | 
					
						
							|  |  |  |    * | 
					
						
							|  |  |  |    * expect(login.valid).toEqual(false); | 
					
						
							| 
									
										
										
										
											2018-06-01 07:35:06 -05:00
										 |  |  |    * expect(login.errors).toEqual({ notUnique: true }); | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  |    * | 
					
						
							| 
									
										
										
										
											2018-06-01 07:35:06 -05:00
										 |  |  |    * login.setValue('someOtherLogin'); | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  |    * | 
					
						
							|  |  |  |    * expect(login.valid).toEqual(true); | 
					
						
							|  |  |  |    * ```
 | 
					
						
							|  |  |  |    */ | 
					
						
							| 
									
										
										
										
											2017-06-12 10:59:29 -07:00
										 |  |  |   setErrors(errors: ValidationErrors|null, opts: {emitEvent?: boolean} = {}): void { | 
					
						
							| 
									
										
										
										
											2017-09-13 14:00:10 -07:00
										 |  |  |     (this as{errors: ValidationErrors | null}).errors = errors; | 
					
						
							| 
									
										
										
										
											2017-06-12 10:59:29 -07:00
										 |  |  |     this._updateControlsErrors(opts.emitEvent !== false); | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-12 20:31:13 -07:00
										 |  |  |   /** | 
					
						
							|  |  |  |    * Retrieves a child control given the control's name or path. | 
					
						
							|  |  |  |    * | 
					
						
							| 
									
										
										
										
											2018-06-11 14:24:00 -05:00
										 |  |  |    * @param path A dot-delimited string or array of string/number values that define the path to the | 
					
						
							| 
									
										
										
										
											2018-06-01 07:35:06 -05:00
										 |  |  |    * control. | 
					
						
							|  |  |  |    * | 
					
						
							| 
									
										
										
										
											2018-09-20 15:18:14 +01:00
										 |  |  |    * @usageNotes | 
					
						
							| 
									
										
										
										
											2018-06-01 07:35:06 -05:00
										 |  |  |    * ### Retrieve a nested control | 
					
						
							| 
									
										
										
										
											2016-09-12 20:31:13 -07:00
										 |  |  |    * | 
					
						
							| 
									
										
										
										
											2018-06-01 07:35:06 -05:00
										 |  |  |    * For example, to get a `name` control nested within a `person` sub-group: | 
					
						
							| 
									
										
										
										
											2016-09-12 20:31:13 -07:00
										 |  |  |    * | 
					
						
							|  |  |  |    * * `this.form.get('person.name');` | 
					
						
							|  |  |  |    * | 
					
						
							|  |  |  |    * -OR- | 
					
						
							|  |  |  |    * | 
					
						
							|  |  |  |    * * `this.form.get(['person', 'name']);` | 
					
						
							|  |  |  |    */ | 
					
						
							| 
									
										
										
										
											2017-04-17 11:13:30 -07:00
										 |  |  |   get(path: Array<string|number>|string): AbstractControl|null { return _find(this, path, '.'); } | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-12 20:31:13 -07:00
										 |  |  |   /** | 
					
						
							| 
									
										
										
										
											2018-12-28 11:00:50 -08:00
										 |  |  |    * @description | 
					
						
							|  |  |  |    * Reports error data for the control with the given path. | 
					
						
							| 
									
										
										
										
											2016-09-12 20:31:13 -07:00
										 |  |  |    * | 
					
						
							| 
									
										
										
										
											2018-12-28 11:00:50 -08:00
										 |  |  |    * @param errorCode The code of the error to check | 
					
						
							|  |  |  |    * @param path A list of control names that designates how to move from the current control | 
					
						
							|  |  |  |    * to the control that should be queried for errors. | 
					
						
							|  |  |  |    * | 
					
						
							|  |  |  |    * @usageNotes | 
					
						
							|  |  |  |    * For example, for the following `FormGroup`: | 
					
						
							| 
									
										
										
										
											2018-06-11 14:24:00 -05:00
										 |  |  |    * | 
					
						
							| 
									
										
										
										
											2018-12-28 11:00:50 -08:00
										 |  |  |    * ```
 | 
					
						
							|  |  |  |    * form = new FormGroup({ | 
					
						
							|  |  |  |    *   address: new FormGroup({ street: new FormControl() }) | 
					
						
							|  |  |  |    * }); | 
					
						
							|  |  |  |    * ```
 | 
					
						
							|  |  |  |    * | 
					
						
							|  |  |  |    * The path to the 'street' control from the root form would be 'address' -> 'street'. | 
					
						
							|  |  |  |    * | 
					
						
							|  |  |  |    * It can be provided to this method in one of two formats: | 
					
						
							|  |  |  |    * | 
					
						
							|  |  |  |    * 1. An array of string control names, e.g. `['address', 'street']` | 
					
						
							|  |  |  |    * 1. A period-delimited list of control names in one string, e.g. `'address.street'` | 
					
						
							|  |  |  |    * | 
					
						
							|  |  |  |    * @returns error data for that particular error. If the control or error is not present, | 
					
						
							|  |  |  |    * null is returned. | 
					
						
							| 
									
										
										
										
											2016-09-12 20:31:13 -07:00
										 |  |  |    */ | 
					
						
							| 
									
										
										
										
											2018-12-22 13:39:37 +13:00
										 |  |  |   getError(errorCode: string, path?: Array<string|number>|string): any { | 
					
						
							| 
									
										
										
										
											2016-10-21 15:14:44 -07:00
										 |  |  |     const control = path ? this.get(path) : this; | 
					
						
							| 
									
										
										
										
											2017-09-13 14:00:10 -07:00
										 |  |  |     return control && control.errors ? control.errors[errorCode] : null; | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-12 20:31:13 -07:00
										 |  |  |   /** | 
					
						
							| 
									
										
										
										
											2018-12-28 11:00:50 -08:00
										 |  |  |    * @description | 
					
						
							| 
									
										
										
										
											2018-06-06 12:17:30 -05:00
										 |  |  |    * Reports whether the control with the given path has the error specified. | 
					
						
							| 
									
										
										
										
											2016-09-12 20:31:13 -07:00
										 |  |  |    * | 
					
						
							| 
									
										
										
										
											2018-12-28 11:00:50 -08:00
										 |  |  |    * @param errorCode The code of the error to check | 
					
						
							|  |  |  |    * @param path A list of control names that designates how to move from the current control | 
					
						
							|  |  |  |    * to the control that should be queried for errors. | 
					
						
							|  |  |  |    * | 
					
						
							|  |  |  |    * @usageNotes | 
					
						
							|  |  |  |    * For example, for the following `FormGroup`: | 
					
						
							|  |  |  |    * | 
					
						
							|  |  |  |    * ```
 | 
					
						
							|  |  |  |    * form = new FormGroup({ | 
					
						
							|  |  |  |    *   address: new FormGroup({ street: new FormControl() }) | 
					
						
							|  |  |  |    * }); | 
					
						
							|  |  |  |    * ```
 | 
					
						
							|  |  |  |    * | 
					
						
							|  |  |  |    * The path to the 'street' control from the root form would be 'address' -> 'street'. | 
					
						
							|  |  |  |    * | 
					
						
							|  |  |  |    * It can be provided to this method in one of two formats: | 
					
						
							|  |  |  |    * | 
					
						
							|  |  |  |    * 1. An array of string control names, e.g. `['address', 'street']` | 
					
						
							|  |  |  |    * 1. A period-delimited list of control names in one string, e.g. `'address.street'` | 
					
						
							|  |  |  |    * | 
					
						
							|  |  |  |    * If no path is given, this method checks for the error on the current control. | 
					
						
							|  |  |  |    * | 
					
						
							|  |  |  |    * @returns whether the given error is present in the control at the given path. | 
					
						
							|  |  |  |    * | 
					
						
							|  |  |  |    * If the control is not present, false is returned. | 
					
						
							| 
									
										
										
										
											2016-09-12 20:31:13 -07:00
										 |  |  |    */ | 
					
						
							| 
									
										
										
										
											2018-12-22 13:39:37 +13:00
										 |  |  |   hasError(errorCode: string, path?: Array<string|number>|string): boolean { | 
					
						
							|  |  |  |     return !!this.getError(errorCode, path); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-12 20:31:13 -07:00
										 |  |  |   /** | 
					
						
							|  |  |  |    * Retrieves the top-level ancestor of this control. | 
					
						
							|  |  |  |    */ | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  |   get root(): AbstractControl { | 
					
						
							|  |  |  |     let x: AbstractControl = this; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-21 15:14:44 -07:00
										 |  |  |     while (x._parent) { | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  |       x = x._parent; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return x; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /** @internal */ | 
					
						
							| 
									
										
										
										
											2016-06-27 21:01:24 -06:00
										 |  |  |   _updateControlsErrors(emitEvent: boolean): void { | 
					
						
							| 
									
										
										
										
											2017-09-13 14:00:10 -07:00
										 |  |  |     (this as{status: string}).status = this._calculateStatus(); | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-27 21:01:24 -06:00
										 |  |  |     if (emitEvent) { | 
					
						
							| 
									
										
										
										
											2017-09-13 14:00:10 -07:00
										 |  |  |       (this.statusChanges as EventEmitter<string>).emit(this.status); | 
					
						
							| 
									
										
										
										
											2016-06-27 21:01:24 -06:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-21 15:14:44 -07:00
										 |  |  |     if (this._parent) { | 
					
						
							| 
									
										
										
										
											2016-06-27 21:01:24 -06:00
										 |  |  |       this._parent._updateControlsErrors(emitEvent); | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /** @internal */ | 
					
						
							|  |  |  |   _initObservables() { | 
					
						
							| 
									
										
										
										
											2017-09-13 14:00:10 -07:00
										 |  |  |     (this as{valueChanges: Observable<any>}).valueChanges = new EventEmitter(); | 
					
						
							|  |  |  |     (this as{statusChanges: Observable<any>}).statusChanges = new EventEmitter(); | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   private _calculateStatus(): string { | 
					
						
							| 
									
										
										
										
											2016-09-01 16:51:42 -07:00
										 |  |  |     if (this._allControlsDisabled()) return DISABLED; | 
					
						
							| 
									
										
										
										
											2017-09-13 14:00:10 -07:00
										 |  |  |     if (this.errors) return INVALID; | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  |     if (this._anyControlsHaveStatus(PENDING)) return PENDING; | 
					
						
							|  |  |  |     if (this._anyControlsHaveStatus(INVALID)) return INVALID; | 
					
						
							|  |  |  |     return VALID; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /** @internal */ | 
					
						
							|  |  |  |   abstract _updateValue(): void; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /** @internal */ | 
					
						
							| 
									
										
										
										
											2016-07-12 15:02:25 -07:00
										 |  |  |   abstract _forEachChild(cb: Function): void; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /** @internal */ | 
					
						
							|  |  |  |   abstract _anyControls(condition: Function): boolean; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-24 16:58:43 -07:00
										 |  |  |   /** @internal */ | 
					
						
							|  |  |  |   abstract _allControlsDisabled(): boolean; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-07 15:39:25 -07:00
										 |  |  |   /** @internal */ | 
					
						
							|  |  |  |   abstract _syncPendingControls(): boolean; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-12 15:02:25 -07:00
										 |  |  |   /** @internal */ | 
					
						
							|  |  |  |   _anyControlsHaveStatus(status: string): boolean { | 
					
						
							| 
									
										
										
										
											2016-10-19 19:55:50 +03:00
										 |  |  |     return this._anyControls((control: AbstractControl) => control.status === status); | 
					
						
							| 
									
										
										
										
											2016-07-12 15:02:25 -07:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /** @internal */ | 
					
						
							|  |  |  |   _anyControlsDirty(): boolean { | 
					
						
							|  |  |  |     return this._anyControls((control: AbstractControl) => control.dirty); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /** @internal */ | 
					
						
							|  |  |  |   _anyControlsTouched(): boolean { | 
					
						
							|  |  |  |     return this._anyControls((control: AbstractControl) => control.touched); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /** @internal */ | 
					
						
							| 
									
										
										
										
											2017-06-12 10:59:29 -07:00
										 |  |  |   _updatePristine(opts: {onlySelf?: boolean} = {}): void { | 
					
						
							| 
									
										
										
										
											2017-09-13 14:00:10 -07:00
										 |  |  |     (this as{pristine: boolean}).pristine = !this._anyControlsDirty(); | 
					
						
							| 
									
										
										
										
											2016-07-12 15:02:25 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-06-12 10:59:29 -07:00
										 |  |  |     if (this._parent && !opts.onlySelf) { | 
					
						
							|  |  |  |       this._parent._updatePristine(opts); | 
					
						
							| 
									
										
										
										
											2016-07-12 15:02:25 -07:00
										 |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /** @internal */ | 
					
						
							| 
									
										
										
										
											2017-06-12 10:59:29 -07:00
										 |  |  |   _updateTouched(opts: {onlySelf?: boolean} = {}): void { | 
					
						
							| 
									
										
										
										
											2017-09-13 14:00:10 -07:00
										 |  |  |     (this as{touched: boolean}).touched = this._anyControlsTouched(); | 
					
						
							| 
									
										
										
										
											2016-07-12 15:02:25 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-06-12 10:59:29 -07:00
										 |  |  |     if (this._parent && !opts.onlySelf) { | 
					
						
							|  |  |  |       this._parent._updateTouched(opts); | 
					
						
							| 
									
										
										
										
											2016-07-12 15:02:25 -07:00
										 |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2016-08-24 16:58:43 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |   /** @internal */ | 
					
						
							| 
									
										
										
										
											2016-09-20 09:08:12 -07:00
										 |  |  |   _onDisabledChange: Function[] = []; | 
					
						
							| 
									
										
										
										
											2016-08-24 16:58:43 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |   /** @internal */ | 
					
						
							|  |  |  |   _isBoxedValue(formState: any): boolean { | 
					
						
							| 
									
										
										
										
											2016-10-19 13:42:39 -07:00
										 |  |  |     return typeof formState === 'object' && formState !== null && | 
					
						
							|  |  |  |         Object.keys(formState).length === 2 && 'value' in formState && 'disabled' in formState; | 
					
						
							| 
									
										
										
										
											2016-08-24 16:58:43 -07:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2016-09-02 15:57:35 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |   /** @internal */ | 
					
						
							|  |  |  |   _registerOnCollectionChange(fn: () => void): void { this._onCollectionChange = fn; } | 
					
						
							| 
									
										
										
										
											2017-08-09 15:41:53 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |   /** @internal */ | 
					
						
							|  |  |  |   _setUpdateStrategy(opts?: ValidatorFn|ValidatorFn[]|AbstractControlOptions|null): void { | 
					
						
							|  |  |  |     if (isOptionsObj(opts) && (opts as AbstractControlOptions).updateOn != null) { | 
					
						
							|  |  |  |       this._updateOn = (opts as AbstractControlOptions).updateOn !; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2018-06-20 17:16:42 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |   /** | 
					
						
							|  |  |  |    * Check to see if parent has been marked artificially dirty. | 
					
						
							|  |  |  |    * | 
					
						
							|  |  |  |    * @internal | 
					
						
							|  |  |  |    */ | 
					
						
							|  |  |  |   private _parentMarkedDirty(onlySelf?: boolean): boolean { | 
					
						
							|  |  |  |     const parentDirty = this._parent && this._parent.dirty; | 
					
						
							|  |  |  |     return !onlySelf && parentDirty && !this._parent._anyControlsDirty(); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /** | 
					
						
							| 
									
										
										
										
											2018-04-05 11:02:42 +01:00
										 |  |  |  * Tracks the value and validation status of an individual form control. | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2018-04-05 11:02:42 +01:00
										 |  |  |  * This is one of the three fundamental building blocks of Angular forms, along with | 
					
						
							| 
									
										
										
										
											2018-06-11 15:48:35 -05:00
										 |  |  |  * `FormGroup` and `FormArray`. It extends the `AbstractControl` class that | 
					
						
							|  |  |  |  * implements most of the base functionality for accessing the value, validation status, | 
					
						
							| 
									
										
										
										
											2018-06-01 07:35:06 -05:00
										 |  |  |  * user interactions and events. | 
					
						
							| 
									
										
										
										
											2018-06-11 15:48:35 -05:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2018-06-01 07:35:06 -05:00
										 |  |  |  * @see `AbstractControl` | 
					
						
							|  |  |  |  * @see [Reactive Forms Guide](guide/reactive-forms) | 
					
						
							|  |  |  |  * @see [Usage Notes](#usage-notes) | 
					
						
							| 
									
										
										
										
											2018-06-11 15:48:35 -05:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2018-06-01 07:35:06 -05:00
										 |  |  |  * @usageNotes | 
					
						
							| 
									
										
										
										
											2018-06-11 15:48:35 -05:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2018-06-11 14:24:00 -05:00
										 |  |  |  * ### Initializing Form Controls | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2018-06-01 07:35:06 -05:00
										 |  |  |  * Instantiate a `FormControl`, with an initial value. | 
					
						
							| 
									
										
										
										
											2016-09-13 00:14:07 -07:00
										 |  |  |  * | 
					
						
							|  |  |  |  * ```ts
 | 
					
						
							| 
									
										
										
										
											2018-07-26 18:57:58 +03:00
										 |  |  |  * const control = new FormControl('some value'); | 
					
						
							|  |  |  |  * console.log(control.value);     // 'some value'
 | 
					
						
							| 
									
										
										
										
											2016-09-13 00:14:07 -07:00
										 |  |  |  *```
 | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2018-06-11 15:48:35 -05:00
										 |  |  |  * The following example initializes the control with a form state object. The `value` | 
					
						
							| 
									
										
										
										
											2018-06-11 14:24:00 -05:00
										 |  |  |  * and `disabled` keys are required in this case. | 
					
						
							| 
									
										
										
										
											2016-09-13 00:14:07 -07:00
										 |  |  |  * | 
					
						
							|  |  |  |  * ```ts
 | 
					
						
							| 
									
										
										
										
											2018-07-26 18:57:58 +03:00
										 |  |  |  * const control = new FormControl({ value: 'n/a', disabled: true }); | 
					
						
							|  |  |  |  * console.log(control.value);     // 'n/a'
 | 
					
						
							|  |  |  |  * console.log(control.status);    // 'DISABLED'
 | 
					
						
							| 
									
										
										
										
											2016-09-13 00:14:07 -07:00
										 |  |  |  * ```
 | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2018-06-01 07:35:06 -05:00
										 |  |  |  * The following example initializes the control with a sync validator. | 
					
						
							| 
									
										
										
										
											2016-09-13 00:14:07 -07:00
										 |  |  |  * | 
					
						
							|  |  |  |  * ```ts
 | 
					
						
							| 
									
										
										
										
											2018-07-26 18:57:58 +03:00
										 |  |  |  * const control = new FormControl('', Validators.required); | 
					
						
							|  |  |  |  * console.log(control.value);      // ''
 | 
					
						
							|  |  |  |  * console.log(control.status);     // 'INVALID'
 | 
					
						
							| 
									
										
										
										
											2016-09-13 00:14:07 -07:00
										 |  |  |  * ```
 | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2018-06-11 14:24:00 -05:00
										 |  |  |  * The following example initializes the control using an options object. | 
					
						
							| 
									
										
										
										
											2017-07-25 15:01:04 -07:00
										 |  |  |  * | 
					
						
							|  |  |  |  * ```ts
 | 
					
						
							| 
									
										
										
										
											2018-07-26 18:57:58 +03:00
										 |  |  |  * const control = new FormControl('', { | 
					
						
							| 
									
										
										
										
											2017-07-25 15:01:04 -07:00
										 |  |  |  *    validators: Validators.required, | 
					
						
							|  |  |  |  *    asyncValidators: myAsyncValidator | 
					
						
							|  |  |  |  * }); | 
					
						
							|  |  |  |  * ```
 | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2018-06-01 07:35:06 -05:00
										 |  |  |  * ### Configure the control to update on a blur event | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Set the `updateOn` option to `'blur'` to update on the blur `event`. | 
					
						
							| 
									
										
										
										
											2017-08-02 18:10:10 -07:00
										 |  |  |  * | 
					
						
							|  |  |  |  * ```ts
 | 
					
						
							| 
									
										
										
										
											2018-07-26 18:57:58 +03:00
										 |  |  |  * const control = new FormControl('', { updateOn: 'blur' }); | 
					
						
							| 
									
										
										
										
											2017-08-02 18:10:10 -07:00
										 |  |  |  * ```
 | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2018-06-01 07:35:06 -05:00
										 |  |  |  * ### Configure the control to update on a submit event | 
					
						
							| 
									
										
										
										
											2017-08-07 15:39:25 -07:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2018-06-01 07:35:06 -05:00
										 |  |  |  * Set the `updateOn` option to `'submit'` to update on a submit `event`. | 
					
						
							| 
									
										
										
										
											2016-09-13 00:14:07 -07:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2018-06-01 07:35:06 -05:00
										 |  |  |  * ```ts
 | 
					
						
							| 
									
										
										
										
											2018-07-26 18:57:58 +03:00
										 |  |  |  * const control = new FormControl('', { updateOn: 'submit' }); | 
					
						
							| 
									
										
										
										
											2018-06-01 07:35:06 -05:00
										 |  |  |  * ```
 | 
					
						
							| 
									
										
										
										
											2018-06-11 15:48:35 -05:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2018-06-01 07:35:06 -05:00
										 |  |  |  * ### Reset the control back to an initial value | 
					
						
							| 
									
										
										
										
											2018-06-11 15:48:35 -05:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2018-06-11 14:24:00 -05:00
										 |  |  |  * You reset to a specific form state by passing through a standalone | 
					
						
							| 
									
										
										
										
											2018-06-01 07:35:06 -05:00
										 |  |  |  * value or a form state object that contains both a value and a disabled state | 
					
						
							|  |  |  |  * (these are the only two properties that cannot be calculated). | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2018-06-01 07:35:06 -05:00
										 |  |  |  * ```ts
 | 
					
						
							| 
									
										
										
										
											2018-07-26 18:57:58 +03:00
										 |  |  |  * const control = new FormControl('Nancy'); | 
					
						
							| 
									
										
										
										
											2018-06-11 15:48:35 -05:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2018-06-01 07:35:06 -05:00
										 |  |  |  * console.log(control.value); // 'Nancy'
 | 
					
						
							| 
									
										
										
										
											2018-06-11 15:48:35 -05:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2018-06-01 07:35:06 -05:00
										 |  |  |  * control.reset('Drew'); | 
					
						
							| 
									
										
										
										
											2018-04-05 22:31:44 +01:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2018-06-01 07:35:06 -05:00
										 |  |  |  * console.log(control.value); // 'Drew'
 | 
					
						
							|  |  |  |  * ```
 | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * ### Reset the control back to an initial value and disabled | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * ```
 | 
					
						
							| 
									
										
										
										
											2018-07-26 18:57:58 +03:00
										 |  |  |  * const control = new FormControl('Nancy'); | 
					
						
							| 
									
										
										
										
											2018-06-11 15:48:35 -05:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2018-06-01 07:35:06 -05:00
										 |  |  |  * console.log(control.value); // 'Nancy'
 | 
					
						
							| 
									
										
										
										
											2018-07-26 18:57:58 +03:00
										 |  |  |  * console.log(control.status); // 'VALID'
 | 
					
						
							| 
									
										
										
										
											2018-06-11 15:48:35 -05:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2018-06-01 07:35:06 -05:00
										 |  |  |  * control.reset({ value: 'Drew', disabled: true }); | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2018-07-26 18:57:58 +03:00
										 |  |  |  * console.log(control.value); // 'Drew'
 | 
					
						
							|  |  |  |  * console.log(control.status); // 'DISABLED'
 | 
					
						
							| 
									
										
										
										
											2018-11-20 20:40:33 +08:00
										 |  |  |  * ```
 | 
					
						
							| 
									
										
										
										
											2018-06-01 07:35:06 -05:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2018-10-19 17:36:24 +01:00
										 |  |  |  * @publicApi | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2016-06-10 11:15:59 -07:00
										 |  |  | export class FormControl extends AbstractControl { | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  |   /** @internal */ | 
					
						
							| 
									
										
										
										
											2016-06-15 15:15:41 -07:00
										 |  |  |   _onChange: Function[] = []; | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-02 18:10:10 -07:00
										 |  |  |   /** @internal */ | 
					
						
							|  |  |  |   _pendingValue: any; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-11 02:54:36 -08:00
										 |  |  |   /** @internal */ | 
					
						
							|  |  |  |   _pendingChange: any; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-06-01 07:35:06 -05:00
										 |  |  |   /** | 
					
						
							|  |  |  |   * Creates a new `FormControl` instance. | 
					
						
							|  |  |  |   * | 
					
						
							| 
									
										
										
										
											2018-06-27 14:33:16 -05:00
										 |  |  |   * @param formState Initializes the control with an initial value, | 
					
						
							|  |  |  |   * or an object that defines the initial value and disabled state. | 
					
						
							| 
									
										
										
										
											2018-06-01 07:35:06 -05:00
										 |  |  |   * | 
					
						
							| 
									
										
										
										
											2018-06-07 13:37:01 -05:00
										 |  |  |   * @param validatorOrOpts A synchronous validator function, or an array of | 
					
						
							|  |  |  |   * such functions, or an `AbstractControlOptions` object that contains validation functions | 
					
						
							| 
									
										
										
										
											2018-06-06 12:17:30 -05:00
										 |  |  |   * and a validation trigger. | 
					
						
							| 
									
										
										
										
											2018-06-01 07:35:06 -05:00
										 |  |  |   * | 
					
						
							|  |  |  |   * @param asyncValidator A single async validator or array of async validator functions | 
					
						
							|  |  |  |   * | 
					
						
							|  |  |  |   */ | 
					
						
							| 
									
										
										
										
											2016-06-08 16:38:52 -07:00
										 |  |  |   constructor( | 
					
						
							| 
									
										
										
										
											2017-07-25 15:01:04 -07:00
										 |  |  |       formState: any = null, | 
					
						
							|  |  |  |       validatorOrOpts?: ValidatorFn|ValidatorFn[]|AbstractControlOptions|null, | 
					
						
							| 
									
										
										
										
											2017-04-17 11:13:30 -07:00
										 |  |  |       asyncValidator?: AsyncValidatorFn|AsyncValidatorFn[]|null) { | 
					
						
							| 
									
										
										
										
											2017-07-25 15:01:04 -07:00
										 |  |  |     super( | 
					
						
							|  |  |  |         coerceToValidator(validatorOrOpts), | 
					
						
							|  |  |  |         coerceToAsyncValidator(asyncValidator, validatorOrOpts)); | 
					
						
							| 
									
										
										
										
											2016-08-24 16:58:43 -07:00
										 |  |  |     this._applyFormState(formState); | 
					
						
							| 
									
										
										
										
											2017-08-02 18:10:10 -07:00
										 |  |  |     this._setUpdateStrategy(validatorOrOpts); | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  |     this.updateValueAndValidity({onlySelf: true, emitEvent: false}); | 
					
						
							|  |  |  |     this._initObservables(); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /** | 
					
						
							| 
									
										
										
										
											2018-06-06 12:17:30 -05:00
										 |  |  |    * Sets a new value for the form control. | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  |    * | 
					
						
							| 
									
										
										
										
											2018-06-06 12:17:30 -05:00
										 |  |  |    * @param value The new value for the control. | 
					
						
							| 
									
										
										
										
											2018-06-11 15:48:35 -05:00
										 |  |  |    * @param options Configuration options that determine how the control proopagates changes | 
					
						
							|  |  |  |    * and emits events when the value changes. | 
					
						
							| 
									
										
										
										
											2018-06-07 13:37:01 -05:00
										 |  |  |    * The configuration options are passed to the {@link AbstractControl#updateValueAndValidity | 
					
						
							|  |  |  |    * updateValueAndValidity} method. | 
					
						
							| 
									
										
										
										
											2016-09-13 11:43:08 -07:00
										 |  |  |    * | 
					
						
							| 
									
										
										
										
											2018-06-07 13:37:01 -05:00
										 |  |  |    * * `onlySelf`: When true, each change only affects this control, and not its parent. Default is | 
					
						
							|  |  |  |    * false. | 
					
						
							| 
									
										
										
										
											2018-06-11 15:48:35 -05:00
										 |  |  |    * * `emitEvent`: When true or not supplied (the default), both the `statusChanges` and | 
					
						
							|  |  |  |    * `valueChanges` | 
					
						
							|  |  |  |    * observables emit events with the latest status and value when the control value is updated. | 
					
						
							|  |  |  |    * When false, no events are emitted. | 
					
						
							|  |  |  |    * * `emitModelToViewChange`: When true or not supplied  (the default), each change triggers an | 
					
						
							|  |  |  |    * `onChange` event to | 
					
						
							| 
									
										
										
										
											2018-06-07 13:37:01 -05:00
										 |  |  |    * update the view. | 
					
						
							| 
									
										
										
										
											2018-06-11 15:48:35 -05:00
										 |  |  |    * * `emitViewToModelChange`: When true or not supplied (the default), each change triggers an | 
					
						
							|  |  |  |    * `ngModelChange` | 
					
						
							| 
									
										
										
										
											2018-06-07 13:37:01 -05:00
										 |  |  |    * event to update the model. | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  |    * | 
					
						
							|  |  |  |    */ | 
					
						
							| 
									
										
										
										
											2017-04-27 13:39:21 -07:00
										 |  |  |   setValue(value: any, options: { | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  |     onlySelf?: boolean, | 
					
						
							|  |  |  |     emitEvent?: boolean, | 
					
						
							| 
									
										
										
										
											2016-07-12 15:02:25 -07:00
										 |  |  |     emitModelToViewChange?: boolean, | 
					
						
							|  |  |  |     emitViewToModelChange?: boolean | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  |   } = {}): void { | 
					
						
							| 
									
										
										
										
											2017-09-13 14:00:10 -07:00
										 |  |  |     (this as{value: any}).value = this._pendingValue = value; | 
					
						
							| 
									
										
										
										
											2017-04-27 13:39:21 -07:00
										 |  |  |     if (this._onChange.length && options.emitModelToViewChange !== false) { | 
					
						
							|  |  |  |       this._onChange.forEach( | 
					
						
							| 
									
										
										
										
											2017-09-13 14:00:10 -07:00
										 |  |  |           (changeFn) => changeFn(this.value, options.emitViewToModelChange !== false)); | 
					
						
							| 
									
										
										
										
											2016-06-15 15:15:41 -07:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2017-04-27 13:39:21 -07:00
										 |  |  |     this.updateValueAndValidity(options); | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-05 13:35:17 -07:00
										 |  |  |   /** | 
					
						
							| 
									
										
										
										
											2016-09-13 00:14:07 -07:00
										 |  |  |    * Patches the value of a control. | 
					
						
							|  |  |  |    * | 
					
						
							| 
									
										
										
										
											2017-10-13 22:27:38 +03:00
										 |  |  |    * This function is functionally the same as {@link FormControl#setValue setValue} at this level. | 
					
						
							|  |  |  |    * It exists for symmetry with {@link FormGroup#patchValue patchValue} on `FormGroups` and | 
					
						
							|  |  |  |    * `FormArrays`, where it does behave differently. | 
					
						
							| 
									
										
										
										
											2018-06-11 15:48:35 -05:00
										 |  |  |    * | 
					
						
							| 
									
										
										
										
											2018-06-11 14:24:00 -05:00
										 |  |  |    * @see `setValue` for options | 
					
						
							| 
									
										
										
										
											2016-08-05 13:35:17 -07:00
										 |  |  |    */ | 
					
						
							|  |  |  |   patchValue(value: any, options: { | 
					
						
							|  |  |  |     onlySelf?: boolean, | 
					
						
							|  |  |  |     emitEvent?: boolean, | 
					
						
							|  |  |  |     emitModelToViewChange?: boolean, | 
					
						
							|  |  |  |     emitViewToModelChange?: boolean | 
					
						
							|  |  |  |   } = {}): void { | 
					
						
							|  |  |  |     this.setValue(value, options); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-13 00:14:07 -07:00
										 |  |  |   /** | 
					
						
							| 
									
										
										
										
											2018-06-11 14:24:00 -05:00
										 |  |  |    * Resets the form control, marking it `pristine` and `untouched`, and setting | 
					
						
							|  |  |  |    * the value to null. | 
					
						
							| 
									
										
										
										
											2016-09-13 00:14:07 -07:00
										 |  |  |    * | 
					
						
							| 
									
										
										
										
											2018-06-27 14:33:16 -05:00
										 |  |  |    * @param formState Resets the control with an initial value, | 
					
						
							|  |  |  |    * or an object that defines the initial value and disabled state. | 
					
						
							| 
									
										
										
										
											2016-09-13 00:14:07 -07:00
										 |  |  |    * | 
					
						
							| 
									
										
										
										
											2018-06-11 15:48:35 -05:00
										 |  |  |    * @param options Configuration options that determine how the control propagates changes | 
					
						
							|  |  |  |    * and emits events after the value changes. | 
					
						
							| 
									
										
										
										
											2016-09-13 00:14:07 -07:00
										 |  |  |    * | 
					
						
							| 
									
										
										
										
											2018-06-07 13:37:01 -05:00
										 |  |  |    * * `onlySelf`: When true, each change only affects this control, and not its parent. Default is | 
					
						
							|  |  |  |    * false. | 
					
						
							| 
									
										
										
										
											2018-06-11 15:48:35 -05:00
										 |  |  |    * * `emitEvent`: When true or not supplied (the default), both the `statusChanges` and | 
					
						
							|  |  |  |    * `valueChanges` | 
					
						
							|  |  |  |    * observables emit events with the latest status and value when the control is reset. | 
					
						
							|  |  |  |    * When false, no events are emitted. | 
					
						
							| 
									
										
										
										
											2016-09-13 11:43:08 -07:00
										 |  |  |    * | 
					
						
							| 
									
										
										
										
											2016-09-13 00:14:07 -07:00
										 |  |  |    */ | 
					
						
							| 
									
										
										
										
											2017-04-27 13:39:21 -07:00
										 |  |  |   reset(formState: any = null, options: {onlySelf?: boolean, emitEvent?: boolean} = {}): void { | 
					
						
							| 
									
										
										
										
											2016-08-24 16:58:43 -07:00
										 |  |  |     this._applyFormState(formState); | 
					
						
							| 
									
										
										
										
											2017-04-27 13:39:21 -07:00
										 |  |  |     this.markAsPristine(options); | 
					
						
							|  |  |  |     this.markAsUntouched(options); | 
					
						
							| 
									
										
										
										
											2017-09-13 14:00:10 -07:00
										 |  |  |     this.setValue(this.value, options); | 
					
						
							| 
									
										
										
										
											2017-11-11 02:54:36 -08:00
										 |  |  |     this._pendingChange = false; | 
					
						
							| 
									
										
										
										
											2016-07-12 15:02:25 -07:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  |   /** | 
					
						
							|  |  |  |    * @internal | 
					
						
							|  |  |  |    */ | 
					
						
							|  |  |  |   _updateValue() {} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /** | 
					
						
							|  |  |  |    * @internal | 
					
						
							|  |  |  |    */ | 
					
						
							| 
									
										
										
										
											2016-07-12 15:02:25 -07:00
										 |  |  |   _anyControls(condition: Function): boolean { return false; } | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-24 16:58:43 -07:00
										 |  |  |   /** | 
					
						
							|  |  |  |    * @internal | 
					
						
							|  |  |  |    */ | 
					
						
							|  |  |  |   _allControlsDisabled(): boolean { return this.disabled; } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  |   /** | 
					
						
							|  |  |  |    * Register a listener for change events. | 
					
						
							| 
									
										
										
										
											2018-06-01 07:35:06 -05:00
										 |  |  |    * | 
					
						
							|  |  |  |    * @param fn The method that is called when the value changes | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  |    */ | 
					
						
							| 
									
										
										
										
											2016-06-15 15:15:41 -07:00
										 |  |  |   registerOnChange(fn: Function): void { this._onChange.push(fn); } | 
					
						
							| 
									
										
										
										
											2016-07-12 15:02:25 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-25 14:37:57 -07:00
										 |  |  |   /** | 
					
						
							|  |  |  |    * @internal | 
					
						
							|  |  |  |    */ | 
					
						
							|  |  |  |   _clearChangeFns(): void { | 
					
						
							|  |  |  |     this._onChange = []; | 
					
						
							| 
									
										
										
										
											2016-09-20 09:08:12 -07:00
										 |  |  |     this._onDisabledChange = []; | 
					
						
							| 
									
										
										
										
											2016-09-02 15:57:35 -07:00
										 |  |  |     this._onCollectionChange = () => {}; | 
					
						
							| 
									
										
										
										
											2016-08-25 14:37:57 -07:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-24 16:58:43 -07:00
										 |  |  |   /** | 
					
						
							|  |  |  |    * Register a listener for disabled events. | 
					
						
							| 
									
										
										
										
											2018-06-01 07:35:06 -05:00
										 |  |  |    * | 
					
						
							|  |  |  |    * @param fn The method that is called when the disabled status changes. | 
					
						
							| 
									
										
										
										
											2016-08-24 16:58:43 -07:00
										 |  |  |    */ | 
					
						
							| 
									
										
										
										
											2016-09-20 09:08:12 -07:00
										 |  |  |   registerOnDisabledChange(fn: (isDisabled: boolean) => void): void { | 
					
						
							|  |  |  |     this._onDisabledChange.push(fn); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2016-08-24 16:58:43 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-12 15:02:25 -07:00
										 |  |  |   /** | 
					
						
							|  |  |  |    * @internal | 
					
						
							|  |  |  |    */ | 
					
						
							|  |  |  |   _forEachChild(cb: Function): void {} | 
					
						
							| 
									
										
										
										
											2016-08-24 16:58:43 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-07 15:39:25 -07:00
										 |  |  |   /** @internal */ | 
					
						
							|  |  |  |   _syncPendingControls(): boolean { | 
					
						
							| 
									
										
										
										
											2017-08-09 15:41:53 -07:00
										 |  |  |     if (this.updateOn === 'submit') { | 
					
						
							| 
									
										
										
										
											2017-08-07 15:39:25 -07:00
										 |  |  |       if (this._pendingDirty) this.markAsDirty(); | 
					
						
							|  |  |  |       if (this._pendingTouched) this.markAsTouched(); | 
					
						
							| 
									
										
										
										
											2017-11-11 02:54:36 -08:00
										 |  |  |       if (this._pendingChange) { | 
					
						
							|  |  |  |         this.setValue(this._pendingValue, {onlySelf: true, emitModelToViewChange: false}); | 
					
						
							|  |  |  |         return true; | 
					
						
							|  |  |  |       } | 
					
						
							| 
									
										
										
										
											2017-08-07 15:39:25 -07:00
										 |  |  |     } | 
					
						
							|  |  |  |     return false; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-24 16:58:43 -07:00
										 |  |  |   private _applyFormState(formState: any) { | 
					
						
							|  |  |  |     if (this._isBoxedValue(formState)) { | 
					
						
							| 
									
										
										
										
											2017-09-13 14:00:10 -07:00
										 |  |  |       (this as{value: any}).value = this._pendingValue = formState.value; | 
					
						
							| 
									
										
										
										
											2016-08-24 16:58:43 -07:00
										 |  |  |       formState.disabled ? this.disable({onlySelf: true, emitEvent: false}) : | 
					
						
							|  |  |  |                            this.enable({onlySelf: true, emitEvent: false}); | 
					
						
							|  |  |  |     } else { | 
					
						
							| 
									
										
										
										
											2017-09-13 14:00:10 -07:00
										 |  |  |       (this as{value: any}).value = this._pendingValue = formState; | 
					
						
							| 
									
										
										
										
											2017-08-02 18:10:10 -07:00
										 |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /** | 
					
						
							| 
									
										
										
										
											2018-04-05 10:58:12 +01:00
										 |  |  |  * Tracks the value and validity state of a group of `FormControl` instances. | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2018-04-05 10:58:12 +01:00
										 |  |  |  * A `FormGroup` aggregates the values of each child `FormControl` into one object, | 
					
						
							| 
									
										
										
										
											2018-06-06 12:17:30 -05:00
										 |  |  |  * with each control name as the key.  It calculates its status by reducing the status values | 
					
						
							| 
									
										
										
										
											2016-09-13 11:43:08 -07:00
										 |  |  |  * of its children. For example, if one of the controls in a group is invalid, the entire | 
					
						
							|  |  |  |  * group becomes invalid. | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2016-06-10 11:15:59 -07:00
										 |  |  |  * `FormGroup` is one of the three fundamental building blocks used to define forms in Angular, | 
					
						
							| 
									
										
										
										
											2018-04-05 10:58:12 +01:00
										 |  |  |  * along with `FormControl` and `FormArray`. | 
					
						
							| 
									
										
										
										
											2016-09-13 11:43:08 -07:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2018-04-05 10:58:12 +01:00
										 |  |  |  * When instantiating a `FormGroup`, pass in a collection of child controls as the first | 
					
						
							| 
									
										
										
										
											2018-06-11 14:24:00 -05:00
										 |  |  |  * argument. The key for each child registers the name for the control. | 
					
						
							| 
									
										
										
										
											2016-09-13 11:43:08 -07:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2018-06-01 07:35:06 -05:00
										 |  |  |  * @usageNotes | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * ### Create a form group with 2 controls | 
					
						
							| 
									
										
										
										
											2016-09-13 11:43:08 -07:00
										 |  |  |  * | 
					
						
							|  |  |  |  * ```
 | 
					
						
							|  |  |  |  * const form = new FormGroup({ | 
					
						
							|  |  |  |  *   first: new FormControl('Nancy', Validators.minLength(2)), | 
					
						
							|  |  |  |  *   last: new FormControl('Drew'), | 
					
						
							|  |  |  |  * }); | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * console.log(form.value);   // {first: 'Nancy', last; 'Drew'}
 | 
					
						
							|  |  |  |  * console.log(form.status);  // 'VALID'
 | 
					
						
							|  |  |  |  * ```
 | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2018-06-01 07:35:06 -05:00
										 |  |  |  * ### Create a form group with a group-level validator | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2018-06-11 14:24:00 -05:00
										 |  |  |  * You include group-level validators as the second arg, or group-level async | 
					
						
							| 
									
										
										
										
											2016-09-13 11:43:08 -07:00
										 |  |  |  * validators as the third arg. These come in handy when you want to perform validation | 
					
						
							|  |  |  |  * that considers the value of more than one child control. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * ```
 | 
					
						
							|  |  |  |  * const form = new FormGroup({ | 
					
						
							|  |  |  |  *   password: new FormControl('', Validators.minLength(2)), | 
					
						
							|  |  |  |  *   passwordConfirm: new FormControl('', Validators.minLength(2)), | 
					
						
							|  |  |  |  * }, passwordMatchValidator); | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  |  * | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2016-09-13 11:43:08 -07:00
										 |  |  |  * function passwordMatchValidator(g: FormGroup) { | 
					
						
							|  |  |  |  *    return g.get('password').value === g.get('passwordConfirm').value | 
					
						
							|  |  |  |  *       ? null : {'mismatch': true}; | 
					
						
							|  |  |  |  * } | 
					
						
							|  |  |  |  * ```
 | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2018-06-11 14:24:00 -05:00
										 |  |  |  * Like `FormControl` instances, you choose to pass in | 
					
						
							| 
									
										
										
										
											2017-07-25 15:01:04 -07:00
										 |  |  |  * validators and async validators as part of an options object. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * ```
 | 
					
						
							|  |  |  |  * const form = new FormGroup({ | 
					
						
							|  |  |  |  *   password: new FormControl('') | 
					
						
							|  |  |  |  *   passwordConfirm: new FormControl('') | 
					
						
							| 
									
										
										
										
											2018-06-01 07:35:06 -05:00
										 |  |  |  * }, { validators: passwordMatchValidator, asyncValidators: otherValidator }); | 
					
						
							| 
									
										
										
										
											2017-07-25 15:01:04 -07:00
										 |  |  |  * ```
 | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2018-06-01 07:35:06 -05:00
										 |  |  |  * ### Set the updateOn property for all controls in a form group | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2018-06-11 14:24:00 -05:00
										 |  |  |  * The options object is used to set a default value for each child | 
					
						
							| 
									
										
										
										
											2017-08-09 15:41:53 -07:00
										 |  |  |  * control's `updateOn` property. If you set `updateOn` to `'blur'` at the
 | 
					
						
							| 
									
										
										
										
											2018-06-11 14:24:00 -05:00
										 |  |  |  * group level, all child controls default to 'blur', unless the child | 
					
						
							| 
									
										
										
										
											2017-08-09 15:41:53 -07:00
										 |  |  |  * has explicitly specified a different `updateOn` value. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * ```ts
 | 
					
						
							|  |  |  |  * const c = new FormGroup({ | 
					
						
							| 
									
										
										
										
											2018-06-01 07:35:06 -05:00
										 |  |  |  *   one: new FormControl() | 
					
						
							|  |  |  |  * }, { updateOn: 'blur' }); | 
					
						
							| 
									
										
										
										
											2017-08-09 15:41:53 -07:00
										 |  |  |  * ```
 | 
					
						
							| 
									
										
										
										
											2018-10-19 17:36:24 +01:00
										 |  |  |  * | 
					
						
							|  |  |  |  * @publicApi | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  |  */ | 
					
						
							| 
									
										
										
										
											2016-06-10 11:15:59 -07:00
										 |  |  | export class FormGroup extends AbstractControl { | 
					
						
							| 
									
										
										
										
											2018-06-01 07:35:06 -05:00
										 |  |  |   /** | 
					
						
							|  |  |  |   * Creates a new `FormGroup` instance. | 
					
						
							|  |  |  |   * | 
					
						
							| 
									
										
										
										
											2018-06-06 12:17:30 -05:00
										 |  |  |   * @param controls A collection of child controls. The key for each child is the name | 
					
						
							| 
									
										
										
										
											2018-06-01 07:35:06 -05:00
										 |  |  |   * under which it is registered. | 
					
						
							|  |  |  |   * | 
					
						
							| 
									
										
										
										
											2018-06-07 13:37:01 -05:00
										 |  |  |   * @param validatorOrOpts A synchronous validator function, or an array of | 
					
						
							|  |  |  |   * such functions, or an `AbstractControlOptions` object that contains validation functions | 
					
						
							| 
									
										
										
										
											2018-06-06 12:17:30 -05:00
										 |  |  |   * and a validation trigger. | 
					
						
							| 
									
										
										
										
											2018-06-01 07:35:06 -05:00
										 |  |  |   * | 
					
						
							|  |  |  |   * @param asyncValidator A single async validator or array of async validator functions | 
					
						
							|  |  |  |   * | 
					
						
							|  |  |  |   */ | 
					
						
							| 
									
										
										
										
											2016-06-08 16:38:52 -07:00
										 |  |  |   constructor( | 
					
						
							| 
									
										
										
										
											2017-07-25 15:01:04 -07:00
										 |  |  |       public controls: {[key: string]: AbstractControl}, | 
					
						
							|  |  |  |       validatorOrOpts?: ValidatorFn|ValidatorFn[]|AbstractControlOptions|null, | 
					
						
							|  |  |  |       asyncValidator?: AsyncValidatorFn|AsyncValidatorFn[]|null) { | 
					
						
							|  |  |  |     super( | 
					
						
							|  |  |  |         coerceToValidator(validatorOrOpts), | 
					
						
							|  |  |  |         coerceToAsyncValidator(asyncValidator, validatorOrOpts)); | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  |     this._initObservables(); | 
					
						
							| 
									
										
										
										
											2017-08-09 15:41:53 -07:00
										 |  |  |     this._setUpdateStrategy(validatorOrOpts); | 
					
						
							| 
									
										
										
										
											2016-09-02 15:57:35 -07:00
										 |  |  |     this._setUpControls(); | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  |     this.updateValueAndValidity({onlySelf: true, emitEvent: false}); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /** | 
					
						
							| 
									
										
										
										
											2016-09-13 11:43:08 -07:00
										 |  |  |    * Registers a control with the group's list of controls. | 
					
						
							|  |  |  |    * | 
					
						
							| 
									
										
										
										
											2018-06-06 12:17:30 -05:00
										 |  |  |    * This method does not update the value or validity of the control. | 
					
						
							|  |  |  |    * Use {@link FormGroup#addControl addControl} instead. | 
					
						
							| 
									
										
										
										
											2018-06-01 07:35:06 -05:00
										 |  |  |    * | 
					
						
							|  |  |  |    * @param name The control name to register in the collection | 
					
						
							|  |  |  |    * @param control Provides the control for the given name | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  |    */ | 
					
						
							| 
									
										
										
										
											2016-06-15 15:15:41 -07:00
										 |  |  |   registerControl(name: string, control: AbstractControl): AbstractControl { | 
					
						
							|  |  |  |     if (this.controls[name]) return this.controls[name]; | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  |     this.controls[name] = control; | 
					
						
							|  |  |  |     control.setParent(this); | 
					
						
							| 
									
										
										
										
											2016-09-02 15:57:35 -07:00
										 |  |  |     control._registerOnCollectionChange(this._onCollectionChange); | 
					
						
							| 
									
										
										
										
											2016-06-15 15:15:41 -07:00
										 |  |  |     return control; | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /** | 
					
						
							|  |  |  |    * Add a control to this group. | 
					
						
							| 
									
										
										
										
											2018-06-07 13:37:01 -05:00
										 |  |  |    * | 
					
						
							| 
									
										
										
										
											2018-06-06 12:17:30 -05:00
										 |  |  |    * This method also updates the value and validity of the control. | 
					
						
							| 
									
										
										
										
											2018-06-01 07:35:06 -05:00
										 |  |  |    * | 
					
						
							|  |  |  |    * @param name The control name to add to the collection | 
					
						
							|  |  |  |    * @param control Provides the control for the given name | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  |    */ | 
					
						
							|  |  |  |   addControl(name: string, control: AbstractControl): void { | 
					
						
							|  |  |  |     this.registerControl(name, control); | 
					
						
							|  |  |  |     this.updateValueAndValidity(); | 
					
						
							| 
									
										
										
										
											2016-09-02 15:57:35 -07:00
										 |  |  |     this._onCollectionChange(); | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /** | 
					
						
							|  |  |  |    * Remove a control from this group. | 
					
						
							| 
									
										
										
										
											2018-06-01 07:35:06 -05:00
										 |  |  |    * | 
					
						
							|  |  |  |    * @param name The control name to remove from the collection | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  |    */ | 
					
						
							|  |  |  |   removeControl(name: string): void { | 
					
						
							| 
									
										
										
										
											2016-09-02 15:57:35 -07:00
										 |  |  |     if (this.controls[name]) this.controls[name]._registerOnCollectionChange(() => {}); | 
					
						
							| 
									
										
										
										
											2016-09-19 17:15:57 -07:00
										 |  |  |     delete (this.controls[name]); | 
					
						
							| 
									
										
										
										
											2016-09-02 15:57:35 -07:00
										 |  |  |     this.updateValueAndValidity(); | 
					
						
							|  |  |  |     this._onCollectionChange(); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /** | 
					
						
							|  |  |  |    * Replace an existing control. | 
					
						
							| 
									
										
										
										
											2018-06-01 07:35:06 -05:00
										 |  |  |    * | 
					
						
							|  |  |  |    * @param name The control name to replace in the collection | 
					
						
							|  |  |  |    * @param control Provides the control for the given name | 
					
						
							| 
									
										
										
										
											2016-09-02 15:57:35 -07:00
										 |  |  |    */ | 
					
						
							|  |  |  |   setControl(name: string, control: AbstractControl): void { | 
					
						
							|  |  |  |     if (this.controls[name]) this.controls[name]._registerOnCollectionChange(() => {}); | 
					
						
							| 
									
										
										
										
											2016-09-19 17:15:57 -07:00
										 |  |  |     delete (this.controls[name]); | 
					
						
							| 
									
										
										
										
											2016-09-02 15:57:35 -07:00
										 |  |  |     if (control) this.registerControl(name, control); | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  |     this.updateValueAndValidity(); | 
					
						
							| 
									
										
										
										
											2016-09-02 15:57:35 -07:00
										 |  |  |     this._onCollectionChange(); | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /** | 
					
						
							| 
									
										
										
										
											2016-09-13 11:43:08 -07:00
										 |  |  |    * Check whether there is an enabled control with the given name in the group. | 
					
						
							|  |  |  |    * | 
					
						
							| 
									
										
										
										
											2018-06-11 14:24:00 -05:00
										 |  |  |    * Reports false for disabled controls. If you'd like to check for existence in the group | 
					
						
							| 
									
										
										
										
											2017-10-13 22:27:38 +03:00
										 |  |  |    * only, use {@link AbstractControl#get get} instead. | 
					
						
							| 
									
										
										
										
											2018-06-01 07:35:06 -05:00
										 |  |  |    * | 
					
						
							|  |  |  |    * @param name The control name to check for existence in the collection | 
					
						
							| 
									
										
										
										
											2018-06-11 14:24:00 -05:00
										 |  |  |    * | 
					
						
							|  |  |  |    * @returns false for disabled controls, true otherwise. | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  |    */ | 
					
						
							|  |  |  |   contains(controlName: string): boolean { | 
					
						
							| 
									
										
										
										
											2016-09-12 15:15:50 -07:00
										 |  |  |     return this.controls.hasOwnProperty(controlName) && this.controls[controlName].enabled; | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-13 11:43:08 -07:00
										 |  |  |   /** | 
					
						
							| 
									
										
										
										
											2018-06-01 07:35:06 -05:00
										 |  |  |    * Sets the value of the `FormGroup`. It accepts an object that matches | 
					
						
							|  |  |  |    * the structure of the group, with control names as keys. | 
					
						
							| 
									
										
										
										
											2016-09-13 11:43:08 -07:00
										 |  |  |    * | 
					
						
							| 
									
										
										
										
											2018-09-20 15:18:14 +01:00
										 |  |  |    * @usageNotes | 
					
						
							| 
									
										
										
										
											2018-06-01 07:35:06 -05:00
										 |  |  |    * ### Set the complete value for the form group | 
					
						
							| 
									
										
										
										
											2016-09-13 11:43:08 -07:00
										 |  |  |    * | 
					
						
							| 
									
										
										
										
											2018-06-01 07:35:06 -05:00
										 |  |  |    * ```
 | 
					
						
							|  |  |  |    * const form = new FormGroup({ | 
					
						
							|  |  |  |    *   first: new FormControl(), | 
					
						
							|  |  |  |    *   last: new FormControl() | 
					
						
							|  |  |  |    * }); | 
					
						
							| 
									
										
										
										
											2016-09-13 11:43:08 -07:00
										 |  |  |    * | 
					
						
							| 
									
										
										
										
											2018-06-01 07:35:06 -05:00
										 |  |  |    * console.log(form.value);   // {first: null, last: null}
 | 
					
						
							| 
									
										
										
										
											2016-09-13 11:43:08 -07:00
										 |  |  |    * | 
					
						
							| 
									
										
										
										
											2018-06-01 07:35:06 -05:00
										 |  |  |    * form.setValue({first: 'Nancy', last: 'Drew'}); | 
					
						
							|  |  |  |    * console.log(form.value);   // {first: 'Nancy', last: 'Drew'}
 | 
					
						
							|  |  |  |    * ```
 | 
					
						
							| 
									
										
										
										
											2018-09-20 15:18:14 +01:00
										 |  |  |    * | 
					
						
							| 
									
										
										
										
											2018-06-07 13:37:01 -05:00
										 |  |  |    * @throws When strict checks fail, such as setting the value of a control | 
					
						
							| 
									
										
										
										
											2018-06-06 12:17:30 -05:00
										 |  |  |    * that doesn't exist or if you excluding the value of a control. | 
					
						
							| 
									
										
										
										
											2018-06-01 07:35:06 -05:00
										 |  |  |    * | 
					
						
							| 
									
										
										
										
											2018-06-06 12:17:30 -05:00
										 |  |  |    * @param value The new value for the control that matches the structure of the group. | 
					
						
							| 
									
										
										
										
											2018-06-11 15:48:35 -05:00
										 |  |  |    * @param options Configuration options that determine how the control propagates changes | 
					
						
							|  |  |  |    * and emits events after the value changes. | 
					
						
							| 
									
										
										
										
											2018-06-07 13:37:01 -05:00
										 |  |  |    * The configuration options are passed to the {@link AbstractControl#updateValueAndValidity | 
					
						
							|  |  |  |    * updateValueAndValidity} method. | 
					
						
							| 
									
										
										
										
											2018-06-06 12:17:30 -05:00
										 |  |  |    * | 
					
						
							| 
									
										
										
										
											2018-06-07 13:37:01 -05:00
										 |  |  |    * * `onlySelf`: When true, each change only affects this control, and not its parent. Default is | 
					
						
							|  |  |  |    * false. | 
					
						
							| 
									
										
										
										
											2018-06-11 15:48:35 -05:00
										 |  |  |    * * `emitEvent`: When true or not supplied (the default), both the `statusChanges` and | 
					
						
							|  |  |  |    * `valueChanges` | 
					
						
							|  |  |  |    * observables emit events with the latest status and value when the control value is updated. | 
					
						
							|  |  |  |    * When false, no events are emitted. | 
					
						
							| 
									
										
										
										
											2016-09-13 11:43:08 -07:00
										 |  |  |    */ | 
					
						
							| 
									
										
										
										
											2017-04-27 13:39:21 -07:00
										 |  |  |   setValue(value: {[key: string]: any}, options: {onlySelf?: boolean, emitEvent?: boolean} = {}): | 
					
						
							|  |  |  |       void { | 
					
						
							| 
									
										
										
										
											2016-08-05 13:35:17 -07:00
										 |  |  |     this._checkAllValuesPresent(value); | 
					
						
							| 
									
										
										
										
											2016-10-03 16:46:05 -07:00
										 |  |  |     Object.keys(value).forEach(name => { | 
					
						
							| 
									
										
										
										
											2016-07-08 13:04:25 -07:00
										 |  |  |       this._throwIfControlMissing(name); | 
					
						
							| 
									
										
										
										
											2017-04-27 13:39:21 -07:00
										 |  |  |       this.controls[name].setValue(value[name], {onlySelf: true, emitEvent: options.emitEvent}); | 
					
						
							| 
									
										
										
										
											2016-08-05 13:35:17 -07:00
										 |  |  |     }); | 
					
						
							| 
									
										
										
										
											2017-04-27 13:39:21 -07:00
										 |  |  |     this.updateValueAndValidity(options); | 
					
						
							| 
									
										
										
										
											2016-08-05 13:35:17 -07:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-13 11:43:08 -07:00
										 |  |  |   /** | 
					
						
							| 
									
										
										
										
											2018-06-01 07:35:06 -05:00
										 |  |  |    * Patches the value of the `FormGroup`. It accepts an object with control | 
					
						
							| 
									
										
										
										
											2018-06-11 14:24:00 -05:00
										 |  |  |    * names as keys, and does its best to match the values to the correct controls | 
					
						
							| 
									
										
										
										
											2018-06-01 07:35:06 -05:00
										 |  |  |    * in the group. | 
					
						
							| 
									
										
										
										
											2016-09-13 11:43:08 -07:00
										 |  |  |    * | 
					
						
							| 
									
										
										
										
											2018-06-01 07:35:06 -05:00
										 |  |  |    * It accepts both super-sets and sub-sets of the group without throwing an error. | 
					
						
							| 
									
										
										
										
											2016-09-13 11:43:08 -07:00
										 |  |  |    * | 
					
						
							| 
									
										
										
										
											2018-09-20 15:18:14 +01:00
										 |  |  |    * @usageNotes | 
					
						
							| 
									
										
										
										
											2018-06-01 07:35:06 -05:00
										 |  |  |    * ### Patch the value for a form group | 
					
						
							| 
									
										
										
										
											2016-09-13 11:43:08 -07:00
										 |  |  |    * | 
					
						
							| 
									
										
										
										
											2018-09-20 15:18:14 +01:00
										 |  |  |    * ```
 | 
					
						
							|  |  |  |    * const form = new FormGroup({ | 
					
						
							|  |  |  |    *    first: new FormControl(), | 
					
						
							|  |  |  |    *    last: new FormControl() | 
					
						
							|  |  |  |    * }); | 
					
						
							|  |  |  |    * console.log(form.value);   // {first: null, last: null}
 | 
					
						
							| 
									
										
										
										
											2016-09-13 11:43:08 -07:00
										 |  |  |    * | 
					
						
							| 
									
										
										
										
											2018-09-20 15:18:14 +01:00
										 |  |  |    * form.patchValue({first: 'Nancy'}); | 
					
						
							|  |  |  |    * console.log(form.value);   // {first: 'Nancy', last: null}
 | 
					
						
							|  |  |  |    * ```
 | 
					
						
							| 
									
										
										
										
											2018-06-01 07:35:06 -05:00
										 |  |  |    * | 
					
						
							| 
									
										
										
										
											2018-09-11 10:21:37 +01:00
										 |  |  |    * @param value The object that matches the structure of the group. | 
					
						
							|  |  |  |    * @param options Configuration options that determine how the control propagates changes and | 
					
						
							|  |  |  |    * emits events after the value is patched. | 
					
						
							|  |  |  |    * * `onlySelf`: When true, each change only affects this control and not its parent. Default is | 
					
						
							| 
									
										
										
										
											2018-06-11 15:48:35 -05:00
										 |  |  |    * true. | 
					
						
							|  |  |  |    * * `emitEvent`: When true or not supplied (the default), both the `statusChanges` and | 
					
						
							|  |  |  |    * `valueChanges` | 
					
						
							|  |  |  |    * observables emit events with the latest status and value when the control value is updated. | 
					
						
							|  |  |  |    * When false, no events are emitted. | 
					
						
							| 
									
										
										
										
											2018-06-07 13:37:01 -05:00
										 |  |  |    * The configuration options are passed to the {@link AbstractControl#updateValueAndValidity | 
					
						
							|  |  |  |    * updateValueAndValidity} method. | 
					
						
							| 
									
										
										
										
											2016-09-13 11:43:08 -07:00
										 |  |  |    */ | 
					
						
							| 
									
										
										
										
											2017-04-27 13:39:21 -07:00
										 |  |  |   patchValue(value: {[key: string]: any}, options: {onlySelf?: boolean, emitEvent?: boolean} = {}): | 
					
						
							|  |  |  |       void { | 
					
						
							| 
									
										
										
										
											2016-10-03 16:46:05 -07:00
										 |  |  |     Object.keys(value).forEach(name => { | 
					
						
							| 
									
										
										
										
											2016-08-05 13:35:17 -07:00
										 |  |  |       if (this.controls[name]) { | 
					
						
							| 
									
										
										
										
											2017-04-27 13:39:21 -07:00
										 |  |  |         this.controls[name].patchValue(value[name], {onlySelf: true, emitEvent: options.emitEvent}); | 
					
						
							| 
									
										
										
										
											2016-08-05 13:35:17 -07:00
										 |  |  |       } | 
					
						
							| 
									
										
										
										
											2016-07-08 13:04:25 -07:00
										 |  |  |     }); | 
					
						
							| 
									
										
										
										
											2017-04-27 13:39:21 -07:00
										 |  |  |     this.updateValueAndValidity(options); | 
					
						
							| 
									
										
										
										
											2016-07-08 13:04:25 -07:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-13 11:43:08 -07:00
										 |  |  |   /** | 
					
						
							| 
									
										
										
										
											2018-06-11 14:24:00 -05:00
										 |  |  |    * Resets the `FormGroup`, marks all descendants are marked `pristine` and `untouched`, and | 
					
						
							|  |  |  |    * the value of all descendants to null. | 
					
						
							| 
									
										
										
										
											2016-09-13 11:43:08 -07:00
										 |  |  |    * | 
					
						
							| 
									
										
										
										
											2018-06-11 14:24:00 -05:00
										 |  |  |    * You reset to a specific form state by passing in a map of states | 
					
						
							| 
									
										
										
										
											2016-09-13 11:43:08 -07:00
										 |  |  |    * that matches the structure of your form, with control names as keys. The state | 
					
						
							| 
									
										
										
										
											2018-06-11 14:24:00 -05:00
										 |  |  |    * is a standalone value or a form state object with both a value and a disabled | 
					
						
							| 
									
										
										
										
											2016-09-13 11:43:08 -07:00
										 |  |  |    * status. | 
					
						
							| 
									
										
										
										
											2018-06-07 13:37:01 -05:00
										 |  |  |    * | 
					
						
							| 
									
										
										
										
											2018-06-27 14:33:16 -05:00
										 |  |  |    * @param formState Resets the control with an initial value, | 
					
						
							|  |  |  |    * or an object that defines the initial value and disabled state. | 
					
						
							| 
									
										
										
										
											2018-06-07 13:37:01 -05:00
										 |  |  |    * | 
					
						
							| 
									
										
										
										
											2018-06-11 14:24:00 -05:00
										 |  |  |    * @param options Configuration options that determine how the control propagates changes | 
					
						
							|  |  |  |    * and emits events when the group is reset. | 
					
						
							| 
									
										
										
										
											2018-06-07 13:37:01 -05:00
										 |  |  |    * * `onlySelf`: When true, each change only affects this control, and not its parent. Default is | 
					
						
							|  |  |  |    * false. | 
					
						
							| 
									
										
										
										
											2018-06-11 15:48:35 -05:00
										 |  |  |    * * `emitEvent`: When true or not supplied (the default), both the `statusChanges` and | 
					
						
							|  |  |  |    * `valueChanges` | 
					
						
							|  |  |  |    * observables emit events with the latest status and value when the control is reset. | 
					
						
							|  |  |  |    * When false, no events are emitted. | 
					
						
							| 
									
										
										
										
											2018-06-07 13:37:01 -05:00
										 |  |  |    * The configuration options are passed to the {@link AbstractControl#updateValueAndValidity | 
					
						
							|  |  |  |    * updateValueAndValidity} method. | 
					
						
							| 
									
										
										
										
											2016-09-13 11:43:08 -07:00
										 |  |  |    * | 
					
						
							| 
									
										
										
										
											2018-06-07 13:31:25 -05:00
										 |  |  |    * @usageNotes | 
					
						
							| 
									
										
										
										
											2018-06-07 13:37:01 -05:00
										 |  |  |    * | 
					
						
							| 
									
										
										
										
											2018-06-01 07:35:06 -05:00
										 |  |  |    * ### Reset the form group values | 
					
						
							| 
									
										
										
										
											2016-09-13 11:43:08 -07:00
										 |  |  |    * | 
					
						
							|  |  |  |    * ```ts
 | 
					
						
							| 
									
										
										
										
											2018-06-01 07:35:06 -05:00
										 |  |  |    * const form = new FormGroup({ | 
					
						
							|  |  |  |    *   first: new FormControl('first name'), | 
					
						
							|  |  |  |    *   last: new FormControl('last name') | 
					
						
							|  |  |  |    * }); | 
					
						
							| 
									
										
										
										
											2016-09-13 11:43:08 -07:00
										 |  |  |    * | 
					
						
							| 
									
										
										
										
											2018-06-01 07:35:06 -05:00
										 |  |  |    * console.log(form.value);  // {first: 'first name', last: 'last name'}
 | 
					
						
							|  |  |  |    * | 
					
						
							|  |  |  |    * form.reset({ first: 'name', last: 'last name' }); | 
					
						
							|  |  |  |    * | 
					
						
							|  |  |  |    * console.log(form.value);  // {first: 'name', last: 'last name'}
 | 
					
						
							| 
									
										
										
										
											2016-09-13 11:43:08 -07:00
										 |  |  |    * ```
 | 
					
						
							|  |  |  |    * | 
					
						
							| 
									
										
										
										
											2018-06-01 07:35:06 -05:00
										 |  |  |    * ### Reset the form group values and disabled status | 
					
						
							| 
									
										
										
										
											2016-09-13 11:43:08 -07:00
										 |  |  |    * | 
					
						
							|  |  |  |    * ```
 | 
					
						
							| 
									
										
										
										
											2018-06-01 07:35:06 -05:00
										 |  |  |    * const form = new FormGroup({ | 
					
						
							|  |  |  |    *   first: new FormControl('first name'), | 
					
						
							|  |  |  |    *   last: new FormControl('last name') | 
					
						
							|  |  |  |    * }); | 
					
						
							|  |  |  |    * | 
					
						
							|  |  |  |    * form.reset({ | 
					
						
							| 
									
										
										
										
											2016-09-13 11:43:08 -07:00
										 |  |  |    *   first: {value: 'name', disabled: true}, | 
					
						
							|  |  |  |    *   last: 'last' | 
					
						
							|  |  |  |    * }); | 
					
						
							|  |  |  |    * | 
					
						
							|  |  |  |    * console.log(this.form.value);  // {first: 'name', last: 'last name'}
 | 
					
						
							|  |  |  |    * console.log(this.form.get('first').status);  // 'DISABLED'
 | 
					
						
							|  |  |  |    * ```
 | 
					
						
							|  |  |  |    */ | 
					
						
							| 
									
										
										
										
											2017-04-27 13:39:21 -07:00
										 |  |  |   reset(value: any = {}, options: {onlySelf?: boolean, emitEvent?: boolean} = {}): void { | 
					
						
							| 
									
										
										
										
											2016-07-12 15:02:25 -07:00
										 |  |  |     this._forEachChild((control: AbstractControl, name: string) => { | 
					
						
							| 
									
										
										
										
											2017-04-27 13:39:21 -07:00
										 |  |  |       control.reset(value[name], {onlySelf: true, emitEvent: options.emitEvent}); | 
					
						
							| 
									
										
										
										
											2016-07-12 15:02:25 -07:00
										 |  |  |     }); | 
					
						
							| 
									
										
										
										
											2017-04-27 13:39:21 -07:00
										 |  |  |     this._updatePristine(options); | 
					
						
							|  |  |  |     this._updateTouched(options); | 
					
						
							| 
									
										
										
										
											2019-01-27 23:59:47 +02:00
										 |  |  |     this.updateValueAndValidity(options); | 
					
						
							| 
									
										
										
										
											2016-07-12 15:02:25 -07:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-13 11:43:08 -07:00
										 |  |  |   /** | 
					
						
							| 
									
										
										
										
											2018-04-05 10:58:12 +01:00
										 |  |  |    * The aggregate value of the `FormGroup`, including any disabled controls. | 
					
						
							| 
									
										
										
										
											2016-09-13 11:43:08 -07:00
										 |  |  |    * | 
					
						
							| 
									
										
										
										
											2018-06-06 12:17:30 -05:00
										 |  |  |    * Retrieves all values regardless of disabled status. | 
					
						
							| 
									
										
										
										
											2018-06-07 13:31:25 -05:00
										 |  |  |    * The `value` property is the best way to get the value of the group, because | 
					
						
							|  |  |  |    * it excludes disabled controls in the `FormGroup`. | 
					
						
							| 
									
										
										
										
											2016-09-13 11:43:08 -07:00
										 |  |  |    */ | 
					
						
							| 
									
										
										
										
											2016-11-09 02:44:36 +03:00
										 |  |  |   getRawValue(): any { | 
					
						
							| 
									
										
										
										
											2016-08-24 16:58:43 -07:00
										 |  |  |     return this._reduceChildren( | 
					
						
							|  |  |  |         {}, (acc: {[k: string]: AbstractControl}, control: AbstractControl, name: string) => { | 
					
						
							| 
									
										
										
										
											2016-11-18 14:44:05 +03:00
										 |  |  |           acc[name] = control instanceof FormControl ? control.value : (<any>control).getRawValue(); | 
					
						
							| 
									
										
										
										
											2016-08-24 16:58:43 -07:00
										 |  |  |           return acc; | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-07 15:39:25 -07:00
										 |  |  |   /** @internal */ | 
					
						
							|  |  |  |   _syncPendingControls(): boolean { | 
					
						
							|  |  |  |     let subtreeUpdated = this._reduceChildren(false, (updated: boolean, child: AbstractControl) => { | 
					
						
							|  |  |  |       return child._syncPendingControls() ? true : updated; | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |     if (subtreeUpdated) this.updateValueAndValidity({onlySelf: true}); | 
					
						
							|  |  |  |     return subtreeUpdated; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-08 13:04:25 -07:00
										 |  |  |   /** @internal */ | 
					
						
							|  |  |  |   _throwIfControlMissing(name: string): void { | 
					
						
							| 
									
										
										
										
											2016-08-05 13:35:17 -07:00
										 |  |  |     if (!Object.keys(this.controls).length) { | 
					
						
							| 
									
										
										
										
											2016-08-25 00:50:16 -07:00
										 |  |  |       throw new Error(`
 | 
					
						
							| 
									
										
										
										
											2016-08-05 13:35:17 -07:00
										 |  |  |         There are no form controls registered with this group yet.  If you're using ngModel, | 
					
						
							|  |  |  |         you may want to check next tick (e.g. use setTimeout). | 
					
						
							|  |  |  |       `);
 | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2016-07-08 13:04:25 -07:00
										 |  |  |     if (!this.controls[name]) { | 
					
						
							| 
									
										
										
										
											2016-08-25 00:50:16 -07:00
										 |  |  |       throw new Error(`Cannot find form control with name: ${name}.`); | 
					
						
							| 
									
										
										
										
											2016-07-08 13:04:25 -07:00
										 |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-12 15:02:25 -07:00
										 |  |  |   /** @internal */ | 
					
						
							| 
									
										
										
										
											2016-07-15 16:26:19 -07:00
										 |  |  |   _forEachChild(cb: (v: any, k: string) => void): void { | 
					
						
							| 
									
										
										
										
											2016-10-03 16:46:05 -07:00
										 |  |  |     Object.keys(this.controls).forEach(k => cb(this.controls[k], k)); | 
					
						
							| 
									
										
										
										
											2016-07-15 16:26:19 -07:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2016-07-12 15:02:25 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  |   /** @internal */ | 
					
						
							| 
									
										
										
										
											2016-10-19 19:55:50 +03:00
										 |  |  |   _setUpControls(): void { | 
					
						
							| 
									
										
										
										
											2016-09-02 15:57:35 -07:00
										 |  |  |     this._forEachChild((control: AbstractControl) => { | 
					
						
							|  |  |  |       control.setParent(this); | 
					
						
							|  |  |  |       control._registerOnCollectionChange(this._onCollectionChange); | 
					
						
							|  |  |  |     }); | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /** @internal */ | 
					
						
							| 
									
										
										
										
											2017-09-13 14:00:10 -07:00
										 |  |  |   _updateValue(): void { (this as{value: any}).value = this._reduceValue(); } | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |   /** @internal */ | 
					
						
							| 
									
										
										
										
											2016-07-12 15:02:25 -07:00
										 |  |  |   _anyControls(condition: Function): boolean { | 
					
						
							| 
									
										
										
										
											2016-10-19 19:55:50 +03:00
										 |  |  |     let res = false; | 
					
						
							| 
									
										
										
										
											2016-07-12 15:02:25 -07:00
										 |  |  |     this._forEachChild((control: AbstractControl, name: string) => { | 
					
						
							|  |  |  |       res = res || (this.contains(name) && condition(control)); | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  |     }); | 
					
						
							|  |  |  |     return res; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /** @internal */ | 
					
						
							|  |  |  |   _reduceValue() { | 
					
						
							|  |  |  |     return this._reduceChildren( | 
					
						
							|  |  |  |         {}, (acc: {[k: string]: AbstractControl}, control: AbstractControl, name: string) => { | 
					
						
							| 
									
										
										
										
											2016-08-24 16:58:43 -07:00
										 |  |  |           if (control.enabled || this.disabled) { | 
					
						
							|  |  |  |             acc[name] = control.value; | 
					
						
							|  |  |  |           } | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  |           return acc; | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /** @internal */ | 
					
						
							|  |  |  |   _reduceChildren(initValue: any, fn: Function) { | 
					
						
							| 
									
										
										
										
											2016-10-19 19:55:50 +03:00
										 |  |  |     let res = initValue; | 
					
						
							| 
									
										
										
										
											2016-08-24 16:58:43 -07:00
										 |  |  |     this._forEachChild( | 
					
						
							|  |  |  |         (control: AbstractControl, name: string) => { res = fn(res, control, name); }); | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  |     return res; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /** @internal */ | 
					
						
							| 
									
										
										
										
											2016-08-24 16:58:43 -07:00
										 |  |  |   _allControlsDisabled(): boolean { | 
					
						
							| 
									
										
										
										
											2016-11-12 14:08:58 +01:00
										 |  |  |     for (const controlName of Object.keys(this.controls)) { | 
					
						
							| 
									
										
										
										
											2016-08-24 16:58:43 -07:00
										 |  |  |       if (this.controls[controlName].enabled) { | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2016-09-08 12:21:48 -07:00
										 |  |  |     return Object.keys(this.controls).length > 0 || this.disabled; | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2016-08-05 13:35:17 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |   /** @internal */ | 
					
						
							|  |  |  |   _checkAllValuesPresent(value: any): void { | 
					
						
							|  |  |  |     this._forEachChild((control: AbstractControl, name: string) => { | 
					
						
							|  |  |  |       if (value[name] === undefined) { | 
					
						
							| 
									
										
										
										
											2016-08-25 00:50:16 -07:00
										 |  |  |         throw new Error(`Must supply a value for form control with name: '${name}'.`); | 
					
						
							| 
									
										
										
										
											2016-08-05 13:35:17 -07:00
										 |  |  |       } | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /** | 
					
						
							| 
									
										
										
										
											2018-04-05 10:58:12 +01:00
										 |  |  |  * Tracks the value and validity state of an array of `FormControl`, | 
					
						
							|  |  |  |  * `FormGroup` or `FormArray` instances. | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2018-04-05 10:58:12 +01:00
										 |  |  |  * A `FormArray` aggregates the values of each child `FormControl` into an array. | 
					
						
							| 
									
										
										
										
											2018-06-06 12:17:30 -05:00
										 |  |  |  * It calculates its status by reducing the status values of its children. For example, if one of | 
					
						
							| 
									
										
										
										
											2016-09-13 13:07:40 -07:00
										 |  |  |  * the controls in a `FormArray` is invalid, the entire array becomes invalid. | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2016-06-10 11:15:59 -07:00
										 |  |  |  * `FormArray` is one of the three fundamental building blocks used to define forms in Angular, | 
					
						
							| 
									
										
										
										
											2018-04-05 10:58:12 +01:00
										 |  |  |  * along with `FormControl` and `FormGroup`. | 
					
						
							| 
									
										
										
										
											2016-09-13 13:07:40 -07:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2018-06-01 07:35:06 -05:00
										 |  |  |  * @usageNotes | 
					
						
							| 
									
										
										
										
											2016-09-13 13:07:40 -07:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2018-06-01 07:35:06 -05:00
										 |  |  |  * ### Create an array of form controls | 
					
						
							| 
									
										
										
										
											2016-09-13 13:07:40 -07:00
										 |  |  |  * | 
					
						
							|  |  |  |  * ```
 | 
					
						
							|  |  |  |  * const arr = new FormArray([ | 
					
						
							|  |  |  |  *   new FormControl('Nancy', Validators.minLength(2)), | 
					
						
							|  |  |  |  *   new FormControl('Drew'), | 
					
						
							|  |  |  |  * ]); | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * console.log(arr.value);   // ['Nancy', 'Drew']
 | 
					
						
							|  |  |  |  * console.log(arr.status);  // 'VALID'
 | 
					
						
							|  |  |  |  * ```
 | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2018-06-01 07:35:06 -05:00
										 |  |  |  * ### Create a form array with array-level validators | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2018-06-11 14:24:00 -05:00
										 |  |  |  * You include array-level validators and async validators. These come in handy | 
					
						
							| 
									
										
										
										
											2017-07-25 15:01:04 -07:00
										 |  |  |  * when you want to perform validation that considers the value of more than one child | 
					
						
							|  |  |  |  * control. | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2018-06-11 14:24:00 -05:00
										 |  |  |  * The two types of validators are passed in separately as the second and third arg | 
					
						
							| 
									
										
										
										
											2017-07-25 15:01:04 -07:00
										 |  |  |  * respectively, or together as part of an options object. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * ```
 | 
					
						
							|  |  |  |  * const arr = new FormArray([ | 
					
						
							|  |  |  |  *   new FormControl('Nancy'), | 
					
						
							|  |  |  |  *   new FormControl('Drew') | 
					
						
							|  |  |  |  * ], {validators: myValidator, asyncValidators: myAsyncValidator}); | 
					
						
							|  |  |  |  * ```
 | 
					
						
							| 
									
										
										
										
											2018-06-01 07:35:06 -05:00
										 |  |  |  * | 
					
						
							|  |  |  |   * ### Set the updateOn property for all controls in a form array | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2018-06-11 14:24:00 -05:00
										 |  |  |  * The options object is used to set a default value for each child | 
					
						
							| 
									
										
										
										
											2017-08-09 15:41:53 -07:00
										 |  |  |  * control's `updateOn` property. If you set `updateOn` to `'blur'` at the
 | 
					
						
							| 
									
										
										
										
											2018-06-11 14:24:00 -05:00
										 |  |  |  * array level, all child controls default to 'blur', unless the child | 
					
						
							| 
									
										
										
										
											2017-08-09 15:41:53 -07:00
										 |  |  |  * has explicitly specified a different `updateOn` value. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * ```ts
 | 
					
						
							| 
									
										
										
										
											2018-06-01 07:35:06 -05:00
										 |  |  |  * const arr = new FormArray([ | 
					
						
							| 
									
										
										
										
											2017-08-09 15:41:53 -07:00
										 |  |  |  *    new FormControl() | 
					
						
							|  |  |  |  * ], {updateOn: 'blur'}); | 
					
						
							|  |  |  |  * ```
 | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2018-06-01 07:35:06 -05:00
										 |  |  |  * ### Adding or removing controls from a form array | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  |  * | 
					
						
							|  |  |  |  * To change the controls in the array, use the `push`, `insert`, or `removeAt` methods | 
					
						
							| 
									
										
										
										
											2016-06-10 11:15:59 -07:00
										 |  |  |  * in `FormArray` itself. These methods ensure the controls are properly tracked in the | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  |  * form's hierarchy. Do not modify the array of `AbstractControl`s used to instantiate | 
					
						
							| 
									
										
										
										
											2018-06-11 14:24:00 -05:00
										 |  |  |  * the `FormArray` directly, as that result in strange and unexpected behavior such | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  |  * as broken change detection. | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2018-10-19 17:36:24 +01:00
										 |  |  |  * @publicApi | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  |  */ | 
					
						
							| 
									
										
										
										
											2016-06-10 11:15:59 -07:00
										 |  |  | export class FormArray extends AbstractControl { | 
					
						
							| 
									
										
										
										
											2018-06-01 07:35:06 -05:00
										 |  |  |   /** | 
					
						
							|  |  |  |   * Creates a new `FormArray` instance. | 
					
						
							|  |  |  |   * | 
					
						
							| 
									
										
										
										
											2018-06-11 14:24:00 -05:00
										 |  |  |   * @param controls An array of child controls. Each child control is given an index | 
					
						
							| 
									
										
										
										
											2018-09-20 10:23:04 +02:00
										 |  |  |   * where it is registered. | 
					
						
							| 
									
										
										
										
											2018-06-01 07:35:06 -05:00
										 |  |  |   * | 
					
						
							| 
									
										
										
										
											2018-06-07 13:37:01 -05:00
										 |  |  |   * @param validatorOrOpts A synchronous validator function, or an array of | 
					
						
							|  |  |  |   * such functions, or an `AbstractControlOptions` object that contains validation functions | 
					
						
							| 
									
										
										
										
											2018-06-06 12:17:30 -05:00
										 |  |  |   * and a validation trigger. | 
					
						
							| 
									
										
										
										
											2018-06-01 07:35:06 -05:00
										 |  |  |   * | 
					
						
							|  |  |  |   * @param asyncValidator A single async validator or array of async validator functions | 
					
						
							|  |  |  |   * | 
					
						
							|  |  |  |   */ | 
					
						
							| 
									
										
										
										
											2016-06-08 16:38:52 -07:00
										 |  |  |   constructor( | 
					
						
							| 
									
										
										
										
											2017-07-25 15:01:04 -07:00
										 |  |  |       public controls: AbstractControl[], | 
					
						
							|  |  |  |       validatorOrOpts?: ValidatorFn|ValidatorFn[]|AbstractControlOptions|null, | 
					
						
							|  |  |  |       asyncValidator?: AsyncValidatorFn|AsyncValidatorFn[]|null) { | 
					
						
							|  |  |  |     super( | 
					
						
							|  |  |  |         coerceToValidator(validatorOrOpts), | 
					
						
							|  |  |  |         coerceToAsyncValidator(asyncValidator, validatorOrOpts)); | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  |     this._initObservables(); | 
					
						
							| 
									
										
										
										
											2017-08-09 15:41:53 -07:00
										 |  |  |     this._setUpdateStrategy(validatorOrOpts); | 
					
						
							| 
									
										
										
										
											2016-09-02 15:57:35 -07:00
										 |  |  |     this._setUpControls(); | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  |     this.updateValueAndValidity({onlySelf: true, emitEvent: false}); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /** | 
					
						
							| 
									
										
										
										
											2018-04-05 10:58:12 +01:00
										 |  |  |    * Get the `AbstractControl` at the given `index` in the array. | 
					
						
							| 
									
										
										
										
											2018-06-01 07:35:06 -05:00
										 |  |  |    * | 
					
						
							|  |  |  |    * @param index Index in the array to retrieve the control | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  |    */ | 
					
						
							|  |  |  |   at(index: number): AbstractControl { return this.controls[index]; } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /** | 
					
						
							| 
									
										
										
										
											2018-04-05 10:58:12 +01:00
										 |  |  |    * Insert a new `AbstractControl` at the end of the array. | 
					
						
							| 
									
										
										
										
											2018-06-01 07:35:06 -05:00
										 |  |  |    * | 
					
						
							|  |  |  |    * @param control Form control to be inserted | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  |    */ | 
					
						
							|  |  |  |   push(control: AbstractControl): void { | 
					
						
							|  |  |  |     this.controls.push(control); | 
					
						
							| 
									
										
										
										
											2016-09-02 15:57:35 -07:00
										 |  |  |     this._registerControl(control); | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  |     this.updateValueAndValidity(); | 
					
						
							| 
									
										
										
										
											2016-09-02 15:57:35 -07:00
										 |  |  |     this._onCollectionChange(); | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-06-01 07:35:06 -05:00
										 |  |  |   /** | 
					
						
							|  |  |  |    * Insert a new `AbstractControl` at the given `index` in the array. | 
					
						
							|  |  |  |    * | 
					
						
							|  |  |  |    * @param index Index in the array to insert the control | 
					
						
							|  |  |  |    * @param control Form control to be inserted | 
					
						
							|  |  |  |    */ | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  |   insert(index: number, control: AbstractControl): void { | 
					
						
							| 
									
										
										
										
											2016-10-19 19:55:50 +03:00
										 |  |  |     this.controls.splice(index, 0, control); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-02 15:57:35 -07:00
										 |  |  |     this._registerControl(control); | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  |     this.updateValueAndValidity(); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-06-01 07:35:06 -05:00
										 |  |  |   /** | 
					
						
							|  |  |  |    * Remove the control at the given `index` in the array. | 
					
						
							|  |  |  |    * | 
					
						
							|  |  |  |    * @param index Index in the array to remove the control | 
					
						
							|  |  |  |    */ | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  |   removeAt(index: number): void { | 
					
						
							| 
									
										
										
										
											2016-09-02 15:57:35 -07:00
										 |  |  |     if (this.controls[index]) this.controls[index]._registerOnCollectionChange(() => {}); | 
					
						
							| 
									
										
										
										
											2016-10-19 19:55:50 +03:00
										 |  |  |     this.controls.splice(index, 1); | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  |     this.updateValueAndValidity(); | 
					
						
							| 
									
										
										
										
											2016-09-02 15:57:35 -07:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /** | 
					
						
							|  |  |  |    * Replace an existing control. | 
					
						
							| 
									
										
										
										
											2018-06-01 07:35:06 -05:00
										 |  |  |    * | 
					
						
							|  |  |  |    * @param index Index in the array to replace the control | 
					
						
							|  |  |  |    * @param control The `AbstractControl` control to replace the existing control | 
					
						
							| 
									
										
										
										
											2016-09-02 15:57:35 -07:00
										 |  |  |    */ | 
					
						
							|  |  |  |   setControl(index: number, control: AbstractControl): void { | 
					
						
							|  |  |  |     if (this.controls[index]) this.controls[index]._registerOnCollectionChange(() => {}); | 
					
						
							| 
									
										
										
										
											2016-10-19 19:55:50 +03:00
										 |  |  |     this.controls.splice(index, 1); | 
					
						
							| 
									
										
										
										
											2016-09-02 15:57:35 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if (control) { | 
					
						
							| 
									
										
										
										
											2016-10-19 19:55:50 +03:00
										 |  |  |       this.controls.splice(index, 0, control); | 
					
						
							| 
									
										
										
										
											2016-09-02 15:57:35 -07:00
										 |  |  |       this._registerControl(control); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     this.updateValueAndValidity(); | 
					
						
							|  |  |  |     this._onCollectionChange(); | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /** | 
					
						
							|  |  |  |    * Length of the control array. | 
					
						
							|  |  |  |    */ | 
					
						
							|  |  |  |   get length(): number { return this.controls.length; } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-13 13:07:40 -07:00
										 |  |  |   /** | 
					
						
							| 
									
										
										
										
											2018-06-01 07:35:06 -05:00
										 |  |  |    * Sets the value of the `FormArray`. It accepts an array that matches | 
					
						
							|  |  |  |    * the structure of the control. | 
					
						
							| 
									
										
										
										
											2016-09-13 13:07:40 -07:00
										 |  |  |    * | 
					
						
							| 
									
										
										
										
											2018-06-11 14:24:00 -05:00
										 |  |  |    * This method performs strict checks, and throws an error if you try | 
					
						
							| 
									
										
										
										
											2016-09-13 13:07:40 -07:00
										 |  |  |    * to set the value of a control that doesn't exist or if you exclude the | 
					
						
							|  |  |  |    * value of a control. | 
					
						
							|  |  |  |    * | 
					
						
							| 
									
										
										
										
											2018-09-20 15:18:14 +01:00
										 |  |  |    * @usageNotes | 
					
						
							| 
									
										
										
										
											2018-06-01 07:35:06 -05:00
										 |  |  |    * ### Set the values for the controls in the form array | 
					
						
							| 
									
										
										
										
											2016-09-13 13:07:40 -07:00
										 |  |  |    * | 
					
						
							| 
									
										
										
										
											2018-06-01 07:35:06 -05:00
										 |  |  |    * ```
 | 
					
						
							|  |  |  |    * const arr = new FormArray([ | 
					
						
							|  |  |  |    *   new FormControl(), | 
					
						
							|  |  |  |    *   new FormControl() | 
					
						
							|  |  |  |    * ]); | 
					
						
							|  |  |  |    * console.log(arr.value);   // [null, null]
 | 
					
						
							|  |  |  |    * | 
					
						
							|  |  |  |    * arr.setValue(['Nancy', 'Drew']); | 
					
						
							|  |  |  |    * console.log(arr.value);   // ['Nancy', 'Drew']
 | 
					
						
							|  |  |  |    * ```
 | 
					
						
							|  |  |  |    * | 
					
						
							| 
									
										
										
										
											2018-06-07 13:31:25 -05:00
										 |  |  |    * @param value Array of values for the controls | 
					
						
							| 
									
										
										
										
											2018-06-11 15:48:35 -05:00
										 |  |  |    * @param options Configure options that determine how the control propagates changes and | 
					
						
							|  |  |  |    * emits events after the value changes | 
					
						
							|  |  |  |    * | 
					
						
							|  |  |  |    * * `onlySelf`: When true, each change only affects this control, and not its parent. Default | 
					
						
							|  |  |  |    * is false. | 
					
						
							|  |  |  |    * * `emitEvent`: When true or not supplied (the default), both the `statusChanges` and | 
					
						
							|  |  |  |    * `valueChanges` | 
					
						
							|  |  |  |    * observables emit events with the latest status and value when the control value is updated. | 
					
						
							|  |  |  |    * When false, no events are emitted. | 
					
						
							| 
									
										
										
										
											2018-06-07 13:37:01 -05:00
										 |  |  |    * The configuration options are passed to the {@link AbstractControl#updateValueAndValidity | 
					
						
							|  |  |  |    * updateValueAndValidity} method. | 
					
						
							| 
									
										
										
										
											2016-09-13 13:07:40 -07:00
										 |  |  |    */ | 
					
						
							| 
									
										
										
										
											2017-04-27 13:39:21 -07:00
										 |  |  |   setValue(value: any[], options: {onlySelf?: boolean, emitEvent?: boolean} = {}): void { | 
					
						
							| 
									
										
										
										
											2016-08-05 13:35:17 -07:00
										 |  |  |     this._checkAllValuesPresent(value); | 
					
						
							| 
									
										
										
										
											2016-07-08 13:04:25 -07:00
										 |  |  |     value.forEach((newValue: any, index: number) => { | 
					
						
							|  |  |  |       this._throwIfControlMissing(index); | 
					
						
							| 
									
										
										
										
											2017-04-27 13:39:21 -07:00
										 |  |  |       this.at(index).setValue(newValue, {onlySelf: true, emitEvent: options.emitEvent}); | 
					
						
							| 
									
										
										
										
											2016-08-05 13:35:17 -07:00
										 |  |  |     }); | 
					
						
							| 
									
										
										
										
											2017-04-27 13:39:21 -07:00
										 |  |  |     this.updateValueAndValidity(options); | 
					
						
							| 
									
										
										
										
											2016-08-05 13:35:17 -07:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-13 13:07:40 -07:00
										 |  |  |   /** | 
					
						
							| 
									
										
										
										
											2018-06-01 07:35:06 -05:00
										 |  |  |    * Patches the value of the `FormArray`. It accepts an array that matches the | 
					
						
							| 
									
										
										
										
											2018-06-11 14:24:00 -05:00
										 |  |  |    * structure of the control, and does its best to match the values to the correct | 
					
						
							| 
									
										
										
										
											2018-06-01 07:35:06 -05:00
										 |  |  |    * controls in the group. | 
					
						
							| 
									
										
										
										
											2016-09-13 13:07:40 -07:00
										 |  |  |    * | 
					
						
							| 
									
										
										
										
											2018-06-01 07:35:06 -05:00
										 |  |  |    * It accepts both super-sets and sub-sets of the array without throwing an error. | 
					
						
							| 
									
										
										
										
											2016-09-13 13:07:40 -07:00
										 |  |  |    * | 
					
						
							| 
									
										
										
										
											2018-09-20 15:18:14 +01:00
										 |  |  |    * @usageNotes | 
					
						
							| 
									
										
										
										
											2018-06-01 07:35:06 -05:00
										 |  |  |    * ### Patch the values for controls in a form array | 
					
						
							| 
									
										
										
										
											2016-09-13 13:07:40 -07:00
										 |  |  |    * | 
					
						
							| 
									
										
										
										
											2018-06-01 07:35:06 -05:00
										 |  |  |    * ```
 | 
					
						
							|  |  |  |    * const arr = new FormArray([ | 
					
						
							|  |  |  |    *    new FormControl(), | 
					
						
							|  |  |  |    *    new FormControl() | 
					
						
							|  |  |  |    * ]); | 
					
						
							|  |  |  |    * console.log(arr.value);   // [null, null]
 | 
					
						
							|  |  |  |    * | 
					
						
							|  |  |  |    * arr.patchValue(['Nancy']); | 
					
						
							|  |  |  |    * console.log(arr.value);   // ['Nancy', null]
 | 
					
						
							|  |  |  |    * ```
 | 
					
						
							|  |  |  |    * | 
					
						
							|  |  |  |    * @param value Array of latest values for the controls | 
					
						
							| 
									
										
										
										
											2018-06-11 15:48:35 -05:00
										 |  |  |    * @param options Configure options that determine how the control propagates changes and | 
					
						
							|  |  |  |    * emits events after the value changes | 
					
						
							|  |  |  |    * | 
					
						
							|  |  |  |    * * `onlySelf`: When true, each change only affects this control, and not its parent. Default | 
					
						
							|  |  |  |    * is false. | 
					
						
							|  |  |  |    * * `emitEvent`: When true or not supplied (the default), both the `statusChanges` and | 
					
						
							|  |  |  |    * `valueChanges` | 
					
						
							|  |  |  |    * observables emit events with the latest status and value when the control value is updated. | 
					
						
							|  |  |  |    * When false, no events are emitted. | 
					
						
							| 
									
										
										
										
											2018-06-07 13:37:01 -05:00
										 |  |  |    * The configuration options are passed to the {@link AbstractControl#updateValueAndValidity | 
					
						
							|  |  |  |    * updateValueAndValidity} method. | 
					
						
							| 
									
										
										
										
											2016-09-13 13:07:40 -07:00
										 |  |  |    */ | 
					
						
							| 
									
										
										
										
											2017-04-27 13:39:21 -07:00
										 |  |  |   patchValue(value: any[], options: {onlySelf?: boolean, emitEvent?: boolean} = {}): void { | 
					
						
							| 
									
										
										
										
											2016-08-05 13:35:17 -07:00
										 |  |  |     value.forEach((newValue: any, index: number) => { | 
					
						
							|  |  |  |       if (this.at(index)) { | 
					
						
							| 
									
										
										
										
											2017-04-27 13:39:21 -07:00
										 |  |  |         this.at(index).patchValue(newValue, {onlySelf: true, emitEvent: options.emitEvent}); | 
					
						
							| 
									
										
										
										
											2016-08-05 13:35:17 -07:00
										 |  |  |       } | 
					
						
							| 
									
										
										
										
											2016-07-08 13:04:25 -07:00
										 |  |  |     }); | 
					
						
							| 
									
										
										
										
											2017-04-27 13:39:21 -07:00
										 |  |  |     this.updateValueAndValidity(options); | 
					
						
							| 
									
										
										
										
											2016-07-08 13:04:25 -07:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-13 13:07:40 -07:00
										 |  |  |   /** | 
					
						
							| 
									
										
										
										
											2018-06-11 14:24:00 -05:00
										 |  |  |    * Resets the `FormArray` and all descendants are marked `pristine` and `untouched`, and the | 
					
						
							|  |  |  |    * value of all descendants to null or null maps. | 
					
						
							| 
									
										
										
										
											2016-09-13 13:07:40 -07:00
										 |  |  |    * | 
					
						
							| 
									
										
										
										
											2018-06-11 14:24:00 -05:00
										 |  |  |    * You reset to a specific form state by passing in an array of states | 
					
						
							|  |  |  |    * that matches the structure of the control. The state is a standalone value | 
					
						
							| 
									
										
										
										
											2016-09-13 13:07:40 -07:00
										 |  |  |    * or a form state object with both a value and a disabled status. | 
					
						
							|  |  |  |    * | 
					
						
							| 
									
										
										
										
											2018-09-20 15:18:14 +01:00
										 |  |  |    * @usageNotes | 
					
						
							| 
									
										
										
										
											2018-06-01 07:35:06 -05:00
										 |  |  |    * ### Reset the values in a form array | 
					
						
							| 
									
										
										
										
											2016-09-13 13:07:40 -07:00
										 |  |  |    * | 
					
						
							|  |  |  |    * ```ts
 | 
					
						
							| 
									
										
										
										
											2018-06-01 07:35:06 -05:00
										 |  |  |    * const arr = new FormArray([ | 
					
						
							|  |  |  |    *    new FormControl(), | 
					
						
							|  |  |  |    *    new FormControl() | 
					
						
							|  |  |  |    * ]); | 
					
						
							|  |  |  |    * arr.reset(['name', 'last name']); | 
					
						
							| 
									
										
										
										
											2016-09-13 13:07:40 -07:00
										 |  |  |    * | 
					
						
							|  |  |  |    * console.log(this.arr.value);  // ['name', 'last name']
 | 
					
						
							|  |  |  |    * ```
 | 
					
						
							|  |  |  |    * | 
					
						
							| 
									
										
										
										
											2018-06-01 07:35:06 -05:00
										 |  |  |    * ### Reset the values in a form array and the disabled status for the first control | 
					
						
							| 
									
										
										
										
											2016-09-13 13:07:40 -07:00
										 |  |  |    * | 
					
						
							|  |  |  |    * ```
 | 
					
						
							|  |  |  |    * this.arr.reset([ | 
					
						
							|  |  |  |    *   {value: 'name', disabled: true}, | 
					
						
							|  |  |  |    *   'last' | 
					
						
							|  |  |  |    * ]); | 
					
						
							|  |  |  |    * | 
					
						
							|  |  |  |    * console.log(this.arr.value);  // ['name', 'last name']
 | 
					
						
							|  |  |  |    * console.log(this.arr.get(0).status);  // 'DISABLED'
 | 
					
						
							|  |  |  |    * ```
 | 
					
						
							| 
									
										
										
										
											2018-06-01 07:35:06 -05:00
										 |  |  |    * | 
					
						
							| 
									
										
										
										
											2018-06-07 13:31:25 -05:00
										 |  |  |    * @param value Array of values for the controls | 
					
						
							| 
									
										
										
										
											2018-06-11 15:48:35 -05:00
										 |  |  |    * @param options Configure options that determine how the control propagates changes and | 
					
						
							|  |  |  |    * emits events after the value changes | 
					
						
							|  |  |  |    * | 
					
						
							|  |  |  |    * * `onlySelf`: When true, each change only affects this control, and not its parent. Default | 
					
						
							|  |  |  |    * is false. | 
					
						
							|  |  |  |    * * `emitEvent`: When true or not supplied (the default), both the `statusChanges` and | 
					
						
							|  |  |  |    * `valueChanges` | 
					
						
							|  |  |  |    * observables emit events with the latest status and value when the control is reset. | 
					
						
							|  |  |  |    * When false, no events are emitted. | 
					
						
							| 
									
										
										
										
											2018-06-07 13:37:01 -05:00
										 |  |  |    * The configuration options are passed to the {@link AbstractControl#updateValueAndValidity | 
					
						
							|  |  |  |    * updateValueAndValidity} method. | 
					
						
							| 
									
										
										
										
											2016-09-13 13:07:40 -07:00
										 |  |  |    */ | 
					
						
							| 
									
										
										
										
											2017-04-27 13:39:21 -07:00
										 |  |  |   reset(value: any = [], options: {onlySelf?: boolean, emitEvent?: boolean} = {}): void { | 
					
						
							| 
									
										
										
										
											2016-07-12 15:02:25 -07:00
										 |  |  |     this._forEachChild((control: AbstractControl, index: number) => { | 
					
						
							| 
									
										
										
										
											2017-04-27 13:39:21 -07:00
										 |  |  |       control.reset(value[index], {onlySelf: true, emitEvent: options.emitEvent}); | 
					
						
							| 
									
										
										
										
											2016-07-12 15:02:25 -07:00
										 |  |  |     }); | 
					
						
							| 
									
										
										
										
											2017-04-27 13:39:21 -07:00
										 |  |  |     this._updatePristine(options); | 
					
						
							|  |  |  |     this._updateTouched(options); | 
					
						
							| 
									
										
										
										
											2019-01-27 23:59:47 +02:00
										 |  |  |     this.updateValueAndValidity(options); | 
					
						
							| 
									
										
										
										
											2016-07-12 15:02:25 -07:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-13 13:07:40 -07:00
										 |  |  |   /** | 
					
						
							|  |  |  |    * The aggregate value of the array, including any disabled controls. | 
					
						
							|  |  |  |    * | 
					
						
							| 
									
										
										
										
											2018-06-07 13:31:25 -05:00
										 |  |  |    * Reports all values regardless of disabled status. | 
					
						
							|  |  |  |    * For enabled controls only, the `value` property is the best way to get the value of the array. | 
					
						
							| 
									
										
										
										
											2016-09-13 13:07:40 -07:00
										 |  |  |    */ | 
					
						
							| 
									
										
										
										
											2016-11-18 14:44:05 +03:00
										 |  |  |   getRawValue(): any[] { | 
					
						
							|  |  |  |     return this.controls.map((control: AbstractControl) => { | 
					
						
							|  |  |  |       return control instanceof FormControl ? control.value : (<any>control).getRawValue(); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2016-08-24 16:58:43 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-07 15:39:25 -07:00
										 |  |  |   /** @internal */ | 
					
						
							|  |  |  |   _syncPendingControls(): boolean { | 
					
						
							|  |  |  |     let subtreeUpdated = this.controls.reduce((updated: boolean, child: AbstractControl) => { | 
					
						
							|  |  |  |       return child._syncPendingControls() ? true : updated; | 
					
						
							|  |  |  |     }, false); | 
					
						
							|  |  |  |     if (subtreeUpdated) this.updateValueAndValidity({onlySelf: true}); | 
					
						
							|  |  |  |     return subtreeUpdated; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-08 13:04:25 -07:00
										 |  |  |   /** @internal */ | 
					
						
							|  |  |  |   _throwIfControlMissing(index: number): void { | 
					
						
							| 
									
										
										
										
											2016-08-05 13:35:17 -07:00
										 |  |  |     if (!this.controls.length) { | 
					
						
							| 
									
										
										
										
											2016-08-25 00:50:16 -07:00
										 |  |  |       throw new Error(`
 | 
					
						
							| 
									
										
										
										
											2016-08-05 13:35:17 -07:00
										 |  |  |         There are no form controls registered with this array yet.  If you're using ngModel, | 
					
						
							|  |  |  |         you may want to check next tick (e.g. use setTimeout). | 
					
						
							|  |  |  |       `);
 | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2016-07-08 13:04:25 -07:00
										 |  |  |     if (!this.at(index)) { | 
					
						
							| 
									
										
										
										
											2016-08-25 00:50:16 -07:00
										 |  |  |       throw new Error(`Cannot find form control at index ${index}`); | 
					
						
							| 
									
										
										
										
											2016-07-08 13:04:25 -07:00
										 |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-12 15:02:25 -07:00
										 |  |  |   /** @internal */ | 
					
						
							|  |  |  |   _forEachChild(cb: Function): void { | 
					
						
							|  |  |  |     this.controls.forEach((control: AbstractControl, index: number) => { cb(control, index); }); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  |   /** @internal */ | 
					
						
							| 
									
										
										
										
											2016-08-24 16:58:43 -07:00
										 |  |  |   _updateValue(): void { | 
					
						
							| 
									
										
										
										
											2017-09-13 14:00:10 -07:00
										 |  |  |     (this as{value: any}).value = | 
					
						
							|  |  |  |         this.controls.filter((control) => control.enabled || this.disabled) | 
					
						
							|  |  |  |             .map((control) => control.value); | 
					
						
							| 
									
										
										
										
											2016-08-24 16:58:43 -07:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |   /** @internal */ | 
					
						
							| 
									
										
										
										
											2016-07-12 15:02:25 -07:00
										 |  |  |   _anyControls(condition: Function): boolean { | 
					
						
							| 
									
										
										
										
											2016-08-24 16:58:43 -07:00
										 |  |  |     return this.controls.some((control: AbstractControl) => control.enabled && condition(control)); | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /** @internal */ | 
					
						
							| 
									
										
										
										
											2016-09-02 15:57:35 -07:00
										 |  |  |   _setUpControls(): void { | 
					
						
							|  |  |  |     this._forEachChild((control: AbstractControl) => this._registerControl(control)); | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2016-08-05 13:35:17 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |   /** @internal */ | 
					
						
							|  |  |  |   _checkAllValuesPresent(value: any): void { | 
					
						
							|  |  |  |     this._forEachChild((control: AbstractControl, i: number) => { | 
					
						
							|  |  |  |       if (value[i] === undefined) { | 
					
						
							| 
									
										
										
										
											2016-08-25 00:50:16 -07:00
										 |  |  |         throw new Error(`Must supply a value for form control at index: ${i}.`); | 
					
						
							| 
									
										
										
										
											2016-08-05 13:35:17 -07:00
										 |  |  |       } | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2016-08-24 16:58:43 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |   /** @internal */ | 
					
						
							|  |  |  |   _allControlsDisabled(): boolean { | 
					
						
							| 
									
										
										
										
											2016-11-12 14:08:58 +01:00
										 |  |  |     for (const control of this.controls) { | 
					
						
							| 
									
										
										
										
											2016-08-24 16:58:43 -07:00
										 |  |  |       if (control.enabled) return false; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2016-09-08 12:21:48 -07:00
										 |  |  |     return this.controls.length > 0 || this.disabled; | 
					
						
							| 
									
										
										
										
											2016-08-24 16:58:43 -07:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2016-09-02 15:57:35 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |   private _registerControl(control: AbstractControl) { | 
					
						
							|  |  |  |     control.setParent(this); | 
					
						
							|  |  |  |     control._registerOnCollectionChange(this._onCollectionChange); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  | } |