From 4e1493a1d6c3d47186458fd14cd0c8da9ab4beed Mon Sep 17 00:00:00 2001 From: Brandon Roberts Date: Fri, 1 Jun 2018 07:35:06 -0500 Subject: [PATCH] docs(forms): update API reference for FormControl (#24255) PR Close #24255 --- packages/forms/src/model.ts | 577 ++++++++++++++++++++++++++---------- 1 file changed, 425 insertions(+), 152 deletions(-) diff --git a/packages/forms/src/model.ts b/packages/forms/src/model.ts index bbda7f1c6b..a94e12839a 100644 --- a/packages/forms/src/model.ts +++ b/packages/forms/src/model.ts @@ -143,7 +143,9 @@ export abstract class AbstractControl { public readonly value: any; /** + * @description * Initialize the AbstractControl instance. + * * @param validator The function that will determine the synchronous validity of this control. * @param asyncValidator The function that will determine the asynchronous validity of this * control. @@ -151,11 +153,13 @@ export abstract class AbstractControl { constructor(public validator: ValidatorFn|null, public asyncValidator: AsyncValidatorFn|null) {} /** + * @description * The parent control. */ get parent(): FormGroup|FormArray { return this._parent; } /** + * @description * The validation status of the control. There are four possible * validation statuses: * @@ -170,7 +174,8 @@ export abstract class AbstractControl { public readonly status: string; /** - * A control is `valid` when its `status === VALID`. + * @description + * A control is `valid` when its `status` is `VALID`. * * In order to have this status, the control must have passed all its * validation checks. @@ -178,7 +183,8 @@ export abstract class AbstractControl { get valid(): boolean { return this.status === VALID; } /** - * A control is `invalid` when its `status === INVALID`. + * @description + * A control is `invalid` when its `status` is `INVALID`. * * In order to have this status, the control must have failed * at least one of its validation checks. @@ -186,7 +192,8 @@ export abstract class AbstractControl { get invalid(): boolean { return this.status === INVALID; } /** - * A control is `pending` when its `status === PENDING`. + * @description + * A control is `pending` when its `status` is `PENDING`. * * In order to have this status, the control must be in the * middle of conducting a validation check. @@ -194,7 +201,8 @@ export abstract class AbstractControl { get pending(): boolean { return this.status == PENDING; } /** - * A control is `disabled` when its `status === DISABLED`. + * @description + * A control is `disabled` when its `status` is `DISABLED`. * * Disabled controls are exempt from validation checks and * are not included in the aggregate value of their ancestor @@ -203,7 +211,8 @@ export abstract class AbstractControl { get disabled(): boolean { return this.status === DISABLED; } /** - * A control is `enabled` as long as its `status !== DISABLED`. + * @description + * A control is `enabled` as long as its `status` is not `DISABLED`. * * In other words, it has a status of `VALID`, `INVALID`, or * `PENDING`. @@ -211,63 +220,73 @@ export abstract class AbstractControl { get enabled(): boolean { return this.status !== DISABLED; } /** + * @description * Returns any errors generated by failing validation. If there * are no errors, it will return null. */ public readonly errors: ValidationErrors|null; /** + * @description * A control is `pristine` if the user has not yet changed * the value in the UI. * - * Note that programmatic changes to a control's value will - * *not* mark it dirty. + * Programmatic changes to a control's value will + * **not** mark it dirty. */ public readonly pristine: boolean = true; /** + * @description * A control is `dirty` if the user has changed the value * in the UI. * - * Note that programmatic changes to a control's value will - * *not* mark it dirty. + * Programmatic changes to a control's value will + * **not** mark it dirty. */ get dirty(): boolean { return !this.pristine; } /** - * A control is marked `touched` once the user has triggered - * a `blur` event on it. - */ + * @description + * A control is marked `touched` once the user has triggered + * a `blur` event on it. + */ public readonly touched: boolean = false; /** + * @description * A control is `untouched` if the user has not yet triggered * a `blur` event on it. */ get untouched(): boolean { return !this.touched; } /** + * @description * Emits an event every time the value of the control changes, in * the UI or programmatically. */ public readonly valueChanges: Observable; /** + * @description * Emits an event every time the validation status of the control * is re-calculated. */ public readonly statusChanges: Observable; /** + * @description * Returns the update strategy of the `AbstractControl` (i.e. * the event on which the control will update itself). - * Possible values: `'change'` (default) | `'blur'` | `'submit'` + * Possible values: `'change'` | `'blur'` | `'submit'` + * Default value: `'change'` */ get updateOn(): FormHooks { return this._updateOn ? this._updateOn : (this.parent ? this.parent.updateOn : 'change'); } /** + * @description * Sets the synchronous validators that are active on this control. Calling * this will overwrite any existing sync validators. */ @@ -276,6 +295,7 @@ export abstract class AbstractControl { } /** + * @description * Sets the async validators that are active on this control. Calling this * will overwrite any existing async validators. */ @@ -284,20 +304,24 @@ export abstract class AbstractControl { } /** + * @description * Empties out the sync validator list. */ clearValidators(): void { this.validator = null; } /** + * @description * Empties out the async validator list. */ clearAsyncValidators(): void { this.asyncValidator = null; } /** + * @description * Marks the control as `touched`. * - * This will also mark all direct ancestors as `touched` to maintain - * the model. + * @param opts Configure options that happen when marked as touched + * * If `onlySelf` is true, this will **not** mark all direct ancestors as `touched` + * to maintain the model. Defaults to false */ markAsTouched(opts: {onlySelf?: boolean} = {}): void { (this as{touched: boolean}).touched = true; @@ -308,11 +332,16 @@ export abstract class AbstractControl { } /** + * @description * Marks the control as `untouched`. * * If the control has any children, it will also mark all children as `untouched` * to maintain the model, and re-calculate the `touched` status of all parent * controls. + * + * @param opts Configure options that happen when marked as untouched + * * If `onlySelf` is true, this will **not** mark all direct ancestors as `touched` + * to maintain the model. Defaults to false */ markAsUntouched(opts: {onlySelf?: boolean} = {}): void { (this as{touched: boolean}).touched = false; @@ -327,10 +356,12 @@ export abstract class AbstractControl { } /** + * @description * Marks the control as `dirty`. * - * This will also mark all direct ancestors as `dirty` to maintain - * the model. + * @param opts Configure options that happen when marked as dirty + * * If `onlySelf` is true, this will **not** mark all direct ancestors as `dirty` to maintain + * to maintain the model. Defaults to false */ markAsDirty(opts: {onlySelf?: boolean} = {}): void { (this as{pristine: boolean}).pristine = false; @@ -341,11 +372,16 @@ export abstract class AbstractControl { } /** + * @description * Marks the control as `pristine`. * * If the control has any children, it will also mark all children as `pristine` * to maintain the model, and re-calculate the `pristine` status of all parent * controls. + * + * @param opts Configure options that happen when marked as pristine + * * If `onlySelf` is true, this will **not** mark all direct ancestors as `pristine` + * to maintain the model. Defaults to false */ markAsPristine(opts: {onlySelf?: boolean} = {}): void { (this as{pristine: boolean}).pristine = true; @@ -359,11 +395,15 @@ export abstract class AbstractControl { } /** + * @description * Marks the control as `pending`. * * An event will be emitted by `statusChanges` by default. * - * Passing `false` for `emitEvent` will cause `statusChanges` to not emit an event. + * @param opts Configure options that happen when marked as untouched + * * If `onlySelf` is true, this will **not** mark all direct ancestors as `untouched` + * to maintain the model. + * * If `emitEvent` is false, `statusChanges` will not emit an event. */ markAsPending(opts: {onlySelf?: boolean, emitEvent?: boolean} = {}): void { (this as{status: string}).status = PENDING; @@ -378,10 +418,16 @@ export abstract class AbstractControl { } /** + * @description * Disables the control. This means the control will be exempt from validation checks and * excluded from the aggregate value of any parent. Its status is `DISABLED`. * * If the control has children, all children will be disabled to maintain the model. + * + * @param opts Configure options that happen when disabled + * * If `onlySelf` is true, this will **not** mark all direct ancestors as `disabled` + * to maintain the model. + * * If `emitEvent` is false, `statusChanges` and `valueChanges` will not emit an event. */ disable(opts: {onlySelf?: boolean, emitEvent?: boolean} = {}): void { (this as{status: string}).status = DISABLED; @@ -400,11 +446,17 @@ export abstract class AbstractControl { } /** + * @description * Enables the control. This means the control will be included in validation checks and * the aggregate value of its parent. Its status is re-calculated based on its value and * its validators. * * If the control has children, all children will be enabled. + * + * @param opts Configure options that happen when marked as untouched + * * If `onlySelf` is true, this will **not** mark all direct ancestors as `disabled` + * to maintain the model. + * * If `emitEvent` is false, `statusChanges` and `valueChanges` will not emit an event. */ enable(opts: {onlySelf?: boolean, emitEvent?: boolean} = {}): void { (this as{status: string}).status = VALID; @@ -424,19 +476,26 @@ export abstract class AbstractControl { } } + /** + * @description + * @param parent Sets the parent of the control + */ setParent(parent: FormGroup|FormArray): void { this._parent = parent; } /** + * @description * Sets the value of the control. Abstract method (implemented in sub-classes). */ abstract setValue(value: any, options?: Object): void; /** + * @description * Patches the value of the control. Abstract method (implemented in sub-classes). */ abstract patchValue(value: any, options?: Object): void; /** + * @description * Resets the control. Abstract method (implemented in sub-classes). */ abstract reset(value?: any, options?: Object): void; @@ -445,6 +504,11 @@ export abstract class AbstractControl { * Re-calculates the value and validation status of the control. * * By default, it will also update the value and validity of its ancestors. + * + * @param opts Configure options that happen when the value and validity change + * * If `onlySelf` is true, this will **not** update all direct ancestors + * to maintain the model. + * * If `emitEvent` is false, `statusChanges` and `valueChanges` will **not** emit an event. */ updateValueAndValidity(opts: {onlySelf?: boolean, emitEvent?: boolean} = {}): void { this._setInitialStatus(); @@ -500,24 +564,25 @@ export abstract class AbstractControl { } /** + * @description * Sets errors on a form control. * * This is used when validations are run manually by the user, rather than automatically. * * Calling `setErrors` will also update the validity of the parent control. * - * ### Example + * ### Manually set the errors for a control * * ``` - * const login = new FormControl("someLogin"); + * const login = new FormControl('someLogin'); * login.setErrors({ - * "notUnique": true + * notUnique: true * }); * * expect(login.valid).toEqual(false); - * expect(login.errors).toEqual({"notUnique": true}); + * expect(login.errors).toEqual({ notUnique: true }); * - * login.setValue("someOtherLogin"); + * login.setValue('someOtherLogin'); * * expect(login.valid).toEqual(true); * ``` @@ -528,11 +593,15 @@ export abstract class AbstractControl { } /** + * @description * Retrieves a child control given the control's name or path. * - * Paths can be passed in as an array or a string delimited by a dot. + * @param path dot-delimited string or array of string/number values that define the path to the + * control. * - * To get a control nested within a `person` sub-group: + * ### Retrieve a nested control + * + * For example, to get a `name` control nested within a `person` sub-group: * * * `this.form.get('person.name');` * @@ -543,10 +612,13 @@ export abstract class AbstractControl { get(path: Array|string): AbstractControl|null { return _find(this, path, '.'); } /** + * @description * Returns error data if the control with the given path has the error specified. Otherwise * returns null or undefined. * - * If no path is given, it checks for the error on the present control. + * @param errorCode The error code to be retrieved + * @param path The path to the control. If no path is given, it checks for the error on the + * present control. */ getError(errorCode: string, path?: string[]): any { const control = path ? this.get(path) : this; @@ -554,14 +626,18 @@ export abstract class AbstractControl { } /** + * @description * Returns true if the control with the given path has the error specified. Otherwise * returns false. * - * If no path is given, it checks for the error on the present control. + * @param errorCode The error code to be retrieved + * @param path The path to the control. If no path is given, it checks for the error on the + * present control. */ hasError(errorCode: string, path?: string[]): boolean { return !!this.getError(errorCode, path); } /** + * @description * Retrieves the top-level ancestor of this control. */ get root(): AbstractControl { @@ -672,45 +748,47 @@ export abstract class AbstractControl { /** * @description - * * Tracks the value and validation status of an individual form control. * * This is one of the three fundamental building blocks of Angular forms, along with - * `FormGroup` and `FormArray`. + * `FormGroup` and `FormArray`. It extends the `AbstractControl` class that + * implements most of the base functionality for accessing the value, validation status, + * user interactions and events. + * + * **npm package**: `@angular/forms` + * + * @see `AbstractControl` + * @see [Reactive Forms Guide](guide/reactive-forms) + * @see [Usage Notes](#usage-notes) + * + * @usageNotes * - * When instantiating a `FormControl`, you can pass in an initial value as the - * first argument. Example: + * Instantiate a `FormControl`, with an initial value. * * ```ts * const ctrl = new FormControl('some value'); * console.log(ctrl.value); // 'some value' *``` * - * You can also initialize the control with a form state object on instantiation, - * which includes both the value and whether or not the control is disabled. - * You can't use the value key without the disabled key; both are required - * to use this way of initialization. + * Initializing the control with a form state object. + * + * The `value` and `disabled` keys are required when initializing with a form state object. * * ```ts - * const ctrl = new FormControl({value: 'n/a', disabled: true}); + * const ctrl = new FormControl({ value: 'n/a', disabled: true }); * console.log(ctrl.value); // 'n/a' - * console.log(ctrl.status); // 'DISABLED' + * console.log(ctrl.status); // 'DISABLED' * ``` * - * The second `FormControl` argument can accept one of three things: - * * a sync validator function - * * an array of sync validator functions - * * an options object containing validator and/or async validator functions - * - * Example of a single sync validator function: + * The following example initializes the control with a sync validator. * * ```ts * const ctrl = new FormControl('', Validators.required); - * console.log(ctrl.value); // '' - * console.log(ctrl.status); // 'INVALID' + * console.log(ctrl.value); // '' + * console.log(ctrl.status); // 'INVALID' * ``` * - * Example using options object: + * The example below initializes the control using an options object. * * ```ts * const ctrl = new FormControl('', { @@ -719,24 +797,52 @@ export abstract class AbstractControl { * }); * ``` * - * The options object can also be used to define when the control should update. - * By default, the value and validity of a control updates whenever the value - * changes. You can configure it to update on the blur event instead by setting - * the `updateOn` option to `'blur'`. + * ### Configure the control to update on a blur event + * + * Set the `updateOn` option to `'blur'` to update on the blur `event`. * * ```ts - * const c = new FormControl('', { updateOn: 'blur' }); + * const ctrl = new FormControl('', { updateOn: 'blur' }); * ``` * - * You can also set `updateOn` to `'submit'`, which will delay value and validity - * updates until the parent form of the control fires a submit event. + * ### Configure the control to update on a submit event * - * See its superclass, `AbstractControl`, for more properties and methods. + * Set the `updateOn` option to `'submit'` to update on a submit `event`. * - * * **npm package**: `@angular/forms` + * ```ts + * const ctrl = new FormControl('', { updateOn: 'submit' }); + * ``` + * + * ### Reset the control back to an initial value + * + * You can also reset to a specific form state by passing through a standalone + * 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). * + * ```ts + * const ctrl = new FormControl('Nancy'); + * + * console.log(control.value); // 'Nancy' + * + * control.reset('Drew'); * - */ + * console.log(control.value); // 'Drew' + * ``` + * + * ### Reset the control back to an initial value and disabled + * + * ``` + * const ctrl = new FormControl('Nancy'); + * + * console.log(control.value); // 'Nancy' + * console.log(this.control.status); // 'DISABLED' + * + * control.reset({ value: 'Drew', disabled: true }); + * + * console.log(this.control.value); // 'Drew' + * console.log(this.control.status); // 'DISABLED' + * +*/ export class FormControl extends AbstractControl { /** @internal */ _onChange: Function[] = []; @@ -747,6 +853,24 @@ export class FormControl extends AbstractControl { /** @internal */ _pendingChange: any; + /** + * @description + * Creates a new `FormControl` instance. + * + * @param formState Provides the control with an initial state in two ways: + * * with an initial value + * * with an object defining the initial value, disabled status and when updates and validation are + *handled. + * + * @param validatorOrOpts Provides the control with one of three things: + * * a sync validator function + * * an array of sync validator functions + * * an options object containing optional validator and/or async validator functions and a + *validation trigger + * + * @param asyncValidator A single async validator or array of async validator functions + * + */ constructor( formState: any = null, validatorOrOpts?: ValidatorFn|ValidatorFn[]|AbstractControlOptions|null, @@ -761,20 +885,23 @@ export class FormControl extends AbstractControl { } /** - * Set the value of the form control to `value`. + * @description + * Sets the latest value form the form control. * - * If `onlySelf` is `true`, this change will only affect the validation of this `FormControl` + * @param value The latest value for the control + * @param options Configure options for emitting events when the control value changes + * + * * If `onlySelf` is `true`, this change will only affect the validation of this `FormControl` * and not its parent component. This defaults to false. * - * If `emitEvent` is `true`, this - * change will cause a `valueChanges` event on the `FormControl` to be emitted. This defaults - * to true (as it falls through to `updateValueAndValidity`). + * * If `emitEvent` is `true`, this change will cause a `valueChanges` event on the `FormControl` + * to be emitted. This defaults to true (as it falls through to `updateValueAndValidity`). * - * If `emitModelToViewChange` is `true`, the view will be notified about the new value + * * If `emitModelToViewChange` is `true`, the view will be notified about the new value * via an `onChange` event. This is the default behavior if `emitModelToViewChange` is not * specified. * - * If `emitViewToModelChange` is `true`, an ngModelChange event will be fired to update the + * * If `emitViewToModelChange` is `true`, an ngModelChange event will be fired to update the * model. This is the default behavior if `emitViewToModelChange` is not specified. */ setValue(value: any, options: { @@ -792,6 +919,7 @@ export class FormControl extends AbstractControl { } /** + * @description * Patches the value of a control. * * This function is functionally the same as {@link FormControl#setValue setValue} at this level. @@ -808,32 +936,28 @@ export class FormControl extends AbstractControl { } /** - * Resets the form control. This means by default: + * @description + * Resets the form control + * + * By default, the following actions happen when the control is reset. * * * it is marked as `pristine` * * it is marked as `untouched` * * value is set to null * - * You can also reset to a specific form state by passing through a standalone - * 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). + * @param formState Provides the control with an initial state in two ways: + * * with an initial value + * * with an object defining the initial value, disabled status and when updates and validation + * are handled. * - * Ex: + * @param options Configure options for emitting events when the control value changes * - * ```ts - * this.control.reset('Nancy'); + * * If `onlySelf` is `true`, this change will only affect the validation of this `FormControl` + * and not its parent component. This defaults to false. * - * console.log(this.control.value); // 'Nancy' - * ``` + * * If `emitEvent` is `true`, this change will cause a `valueChanges` event on the `FormControl` + * to be emitted. This defaults to true (as it falls through to `updateValueAndValidity`). * - * OR - * - * ``` - * this.control.reset({value: 'Nancy', disabled: true}); - * - * console.log(this.control.value); // 'Nancy' - * console.log(this.control.status); // 'DISABLED' - * ``` */ reset(formState: any = null, options: {onlySelf?: boolean, emitEvent?: boolean} = {}): void { this._applyFormState(formState); @@ -859,7 +983,10 @@ export class FormControl extends AbstractControl { _allControlsDisabled(): boolean { return this.disabled; } /** + * @description * Register a listener for change events. + * + * @param fn The method that is called when the value changes */ registerOnChange(fn: Function): void { this._onChange.push(fn); } @@ -873,7 +1000,10 @@ export class FormControl extends AbstractControl { } /** + * @description * Register a listener for disabled events. + * + * @param fn The method that is called when the disabled status changes. */ registerOnDisabledChange(fn: (isDisabled: boolean) => void): void { this._onDisabledChange.push(fn); @@ -924,7 +1054,11 @@ export class FormControl extends AbstractControl { * When instantiating a `FormGroup`, pass in a collection of child controls as the first * argument. The key for each child will be the name under which it is registered. * - * ### Example + * * **npm package**: `@angular/forms` + * + * @usageNotes + * + * ### Create a form group with 2 controls * * ``` * const form = new FormGroup({ @@ -936,12 +1070,12 @@ export class FormControl extends AbstractControl { * console.log(form.status); // 'VALID' * ``` * + * ### Create a form group with a group-level validator + * * You can also include group-level validators as the second arg, or group-level async * 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. * - * ### Example - * * ``` * const form = new FormGroup({ * password: new FormControl('', Validators.minLength(2)), @@ -962,9 +1096,11 @@ export class FormControl extends AbstractControl { * const form = new FormGroup({ * password: new FormControl('') * passwordConfirm: new FormControl('') - * }, {validators: passwordMatchValidator, asyncValidators: otherValidator}); + * }, { validators: passwordMatchValidator, asyncValidators: otherValidator }); * ``` * + * ### Set the updateOn property for all controls in a form group + * * The options object can also be used to set a default value for each child * control's `updateOn` property. If you set `updateOn` to `'blur'` at the * group level, all child controls will default to 'blur', unless the child @@ -972,15 +1108,27 @@ export class FormControl extends AbstractControl { * * ```ts * const c = new FormGroup({ - * one: new FormControl() - * }, {updateOn: 'blur'}); + * one: new FormControl() + * }, { updateOn: 'blur' }); * ``` - * - * * **npm package**: `@angular/forms` - * - * */ export class FormGroup extends AbstractControl { + /** + * @description + * Creates a new `FormGroup` instance. + * + * @param controls A collection of child controls. The key for each child will be the name + * under which it is registered. + * + * @param validatorOrOpts Provides the control with one of three things: + * * a sync validator function + * * an array of sync validator functions + * * an options object containing optional validator and/or async validator functions and a + *validation trigger + * + * @param asyncValidator A single async validator or array of async validator functions + * + */ constructor( public controls: {[key: string]: AbstractControl}, validatorOrOpts?: ValidatorFn|ValidatorFn[]|AbstractControlOptions|null, @@ -995,10 +1143,14 @@ export class FormGroup extends AbstractControl { } /** + * @description * Registers a control with the group's list of controls. * * This method does not update the value or validity of the control, so for most cases you'll want * to use {@link FormGroup#addControl addControl} instead. + * + * @param name The control name to register in the collection + * @param control Provides the control for the given name */ registerControl(name: string, control: AbstractControl): AbstractControl { if (this.controls[name]) return this.controls[name]; @@ -1009,7 +1161,11 @@ export class FormGroup extends AbstractControl { } /** + * @description * Add a control to this group. + * + * @param name The control name to add to the collection + * @param control Provides the control for the given name */ addControl(name: string, control: AbstractControl): void { this.registerControl(name, control); @@ -1018,7 +1174,10 @@ export class FormGroup extends AbstractControl { } /** + * @description * Remove a control from this group. + * + * @param name The control name to remove from the collection */ removeControl(name: string): void { if (this.controls[name]) this.controls[name]._registerOnCollectionChange(() => {}); @@ -1028,7 +1187,11 @@ export class FormGroup extends AbstractControl { } /** + * @description * Replace an existing control. + * + * @param name The control name to replace in the collection + * @param control Provides the control for the given name */ setControl(name: string, control: AbstractControl): void { if (this.controls[name]) this.controls[name]._registerOnCollectionChange(() => {}); @@ -1039,35 +1202,47 @@ export class FormGroup extends AbstractControl { } /** + * @description * Check whether there is an enabled control with the given name in the group. * * It will return false for disabled controls. If you'd like to check for existence in the group * only, use {@link AbstractControl#get get} instead. + * + * @param name The control name to check for existence in the collection */ contains(controlName: string): boolean { return this.controls.hasOwnProperty(controlName) && this.controls[controlName].enabled; } /** - * Sets the value of the `FormGroup`. It accepts an object that matches - * the structure of the group, with control names as keys. + * @description + * Sets the value of the `FormGroup`. It accepts an object that matches + * the structure of the group, with control names as keys. * - * ### Example + * ### Set the complete value for the form group * - * ``` - * const form = new FormGroup({ - * first: new FormControl(), - * last: new FormControl() - * }); - * console.log(form.value); // {first: null, last: null} + * ``` + * const form = new FormGroup({ + * first: new FormControl(), + * last: new FormControl() + * }); * - * form.setValue({first: 'Nancy', last: 'Drew'}); - * console.log(form.value); // {first: 'Nancy', last: 'Drew'} + * console.log(form.value); // {first: null, last: null} * - * ``` + * form.setValue({first: 'Nancy', last: 'Drew'}); + * console.log(form.value); // {first: 'Nancy', last: 'Drew'} + * + * ``` * @throws This method performs strict checks, so it will throw an error if you try * to set the value of a control that doesn't exist or if you exclude the * value of a control. + * + * @param value The object that matches the structure of the group + * @param options Configure options that happen when the value is set + * * If `onlySelf` is true, this will **not** update the value and validity for all direct + * ancestors + * to maintain the model. + * * If `emitEvent` is false, `statusChanges` will not emit an event. */ setValue(value: {[key: string]: any}, options: {onlySelf?: boolean, emitEvent?: boolean} = {}): void { @@ -1080,13 +1255,14 @@ export class FormGroup extends AbstractControl { } /** - * Patches the value of the `FormGroup`. It accepts an object with control - * names as keys, and will do its best to match the values to the correct controls - * in the group. + * @description + * Patches the value of the `FormGroup`. It accepts an object with control + * names as keys, and will do its best to match the values to the correct controls + * in the group. * - * It accepts both super-sets and sub-sets of the group without throwing an error. + * It accepts both super-sets and sub-sets of the group without throwing an error. * - * ### Example + * ### Patch the value for a form group * * ``` * const form = new FormGroup({ @@ -1099,6 +1275,13 @@ export class FormGroup extends AbstractControl { * console.log(form.value); // {first: 'Nancy', last: null} * * ``` + * + * @param value The object that matches the structure of the group + * @param options Configure options that happen when the value is patched + * * If `onlySelf` is true, this will **not** update the value and validity for all direct + * ancestors + * to maintain the model. + * * If `emitEvent` is false, `statusChanges` will not emit an event. */ patchValue(value: {[key: string]: any}, options: {onlySelf?: boolean, emitEvent?: boolean} = {}): void { @@ -1111,6 +1294,7 @@ export class FormGroup extends AbstractControl { } /** + * @description * Resets the `FormGroup`. This means by default: * * * The group and all descendants are marked `pristine` @@ -1122,18 +1306,30 @@ export class FormGroup extends AbstractControl { * can be a standalone value or a form state object with both a value and a disabled * status. * - * ### Example + * ### Reset the form group values * * ```ts - * this.form.reset({first: 'name', last: 'last name'}); + * const form = new FormGroup({ + * first: new FormControl('first name'), + * last: new FormControl('last name') + * }); * - * console.log(this.form.value); // {first: 'name', last: 'last name'} + * 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'} * ``` * - * - OR - + * ### Reset the form group values and disabled status * * ``` - * this.form.reset({ + * const form = new FormGroup({ + * first: new FormControl('first name'), + * last: new FormControl('last name') + * }); + * + * form.reset({ * first: {value: 'name', disabled: true}, * last: 'last' * }); @@ -1152,10 +1348,11 @@ export class FormGroup extends AbstractControl { } /** + * @description * The aggregate value of the `FormGroup`, including any disabled controls. * - * If you'd like to include all values regardless of disabled status, use this method. - * Otherwise, the `value` property is the best way to get the value of the group. + * Retrieve all values regardless of disabled status. + * The `value` property is the best way to get the value of the group. */ getRawValue(): any { return this._reduceChildren( @@ -1264,10 +1461,11 @@ export class FormGroup extends AbstractControl { * `FormArray` is one of the three fundamental building blocks used to define forms in Angular, * along with `FormControl` and `FormGroup`. * - * When instantiating a `FormArray`, pass in an array of child controls as the first - * argument. + * * **npm package**: `@angular/forms` * - * ### Example + * @usageNotes + * + * ### Create an array of form controls * * ``` * const arr = new FormArray([ @@ -1279,6 +1477,8 @@ export class FormGroup extends AbstractControl { * console.log(arr.status); // 'VALID' * ``` * + * ### Create a form array with array-level validators + * * You can also include array-level validators and async validators. These come in handy * when you want to perform validation that considers the value of more than one child * control. @@ -1292,6 +1492,8 @@ export class FormGroup extends AbstractControl { * new FormControl('Drew') * ], {validators: myValidator, asyncValidators: myAsyncValidator}); * ``` + * + * ### Set the updateOn property for all controls in a form array * * The options object can also be used to set a default value for each child * control's `updateOn` property. If you set `updateOn` to `'blur'` at the @@ -1299,12 +1501,12 @@ export class FormGroup extends AbstractControl { * has explicitly specified a different `updateOn` value. * * ```ts - * const c = new FormArray([ + * const arr = new FormArray([ * new FormControl() * ], {updateOn: 'blur'}); * ``` * - * ### Adding or removing controls + * ### Adding or removing controls from a form array * * To change the controls in the array, use the `push`, `insert`, or `removeAt` methods * in `FormArray` itself. These methods ensure the controls are properly tracked in the @@ -1312,11 +1514,25 @@ export class FormGroup extends AbstractControl { * the `FormArray` directly, as that will result in strange and unexpected behavior such * as broken change detection. * - * * **npm package**: `@angular/forms` - * * */ export class FormArray extends AbstractControl { + /** + * @description + * Creates a new `FormArray` instance. + * + * @param controls An array of child controls. Each child control will be given an index + * wheh it is registered. + * + * @param validatorOrOpts Provides the control with one of three things: + * * a sync validator function + * * an array of sync validator functions + * * an options object containing optional validator and/or async validator functions and a + *validation trigger + * + * @param asyncValidator A single async validator or array of async validator functions + * + */ constructor( public controls: AbstractControl[], validatorOrOpts?: ValidatorFn|ValidatorFn[]|AbstractControlOptions|null, @@ -1331,12 +1547,18 @@ export class FormArray extends AbstractControl { } /** + * @description * Get the `AbstractControl` at the given `index` in the array. + * + * @param index Index in the array to retrieve the control */ at(index: number): AbstractControl { return this.controls[index]; } /** + * @description * Insert a new `AbstractControl` at the end of the array. + * + * @param control Form control to be inserted */ push(control: AbstractControl): void { this.controls.push(control); @@ -1345,7 +1567,13 @@ export class FormArray extends AbstractControl { this._onCollectionChange(); } - /** Insert a new `AbstractControl` at the given `index` in the array. */ + /** + * @description + * 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 + */ insert(index: number, control: AbstractControl): void { this.controls.splice(index, 0, control); @@ -1353,7 +1581,12 @@ export class FormArray extends AbstractControl { this.updateValueAndValidity(); } - /** Remove the control at the given `index` in the array. */ + /** + * @description + * Remove the control at the given `index` in the array. + * + * @param index Index in the array to remove the control + */ removeAt(index: number): void { if (this.controls[index]) this.controls[index]._registerOnCollectionChange(() => {}); this.controls.splice(index, 1); @@ -1361,7 +1594,11 @@ export class FormArray extends AbstractControl { } /** + * @description * Replace an existing control. + * + * @param index Index in the array to replace the control + * @param control The `AbstractControl` control to replace the existing control */ setControl(index: number, control: AbstractControl): void { if (this.controls[index]) this.controls[index]._registerOnCollectionChange(() => {}); @@ -1377,30 +1614,41 @@ export class FormArray extends AbstractControl { } /** + * @description * Length of the control array. */ get length(): number { return this.controls.length; } /** - * Sets the value of the `FormArray`. It accepts an array that matches - * the structure of the control. + * @description + * Sets the value of the `FormArray`. It accepts an array that matches + * the structure of the control. * * This method performs strict checks, so it will throw an error if you try * to set the value of a control that doesn't exist or if you exclude the * value of a control. * - * ### Example + * ### Set the values for the controls in the form array * - * ``` - * const arr = new FormArray([ - * new FormControl(), - * new FormControl() - * ]); - * console.log(arr.value); // [null, null] + * ``` + * const arr = new FormArray([ + * new FormControl(), + * new FormControl() + * ]); + * console.log(arr.value); // [null, null] * - * arr.setValue(['Nancy', 'Drew']); - * console.log(arr.value); // ['Nancy', 'Drew'] - * ``` + * arr.setValue(['Nancy', 'Drew']); + * console.log(arr.value); // ['Nancy', 'Drew'] + * ``` + * + * @param value Array of latest values for the controls + * @param options Configure options for emitting events when the control value changes + * + * * If `onlySelf` is `true`, this change will only affect the validation of this `FormArray` + * and not its parent component. This defaults to false. + * + * * If `emitEvent` is `true`, this change will cause a `valueChanges` event on the `FormArray` + * to be emitted. This defaults to true (as it falls through to `updateValueAndValidity`). */ setValue(value: any[], options: {onlySelf?: boolean, emitEvent?: boolean} = {}): void { this._checkAllValuesPresent(value); @@ -1412,24 +1660,34 @@ export class FormArray extends AbstractControl { } /** - * Patches the value of the `FormArray`. It accepts an array that matches the - * structure of the control, and will do its best to match the values to the correct - * controls in the group. + * @description + * Patches the value of the `FormArray`. It accepts an array that matches the + * structure of the control, and will do its best to match the values to the correct + * controls in the group. * - * It accepts both super-sets and sub-sets of the array without throwing an error. + * It accepts both super-sets and sub-sets of the array without throwing an error. * - * ### Example + * ### Patch the values for controls in a form array * - * ``` - * const arr = new FormArray([ - * new FormControl(), - * new FormControl() - * ]); - * console.log(arr.value); // [null, null] + * ``` + * const arr = new FormArray([ + * new FormControl(), + * new FormControl() + * ]); + * console.log(arr.value); // [null, null] * - * arr.patchValue(['Nancy']); - * console.log(arr.value); // ['Nancy', null] - * ``` + * arr.patchValue(['Nancy']); + * console.log(arr.value); // ['Nancy', null] + * ``` + * + * @param value Array of latest values for the controls + * @param options Configure options for emitting events when the control value changes + * + * * If `onlySelf` is `true`, this change will only affect the validation of this `FormArray` + * and not its parent component. This defaults to false. + * + * * If `emitEvent` is `true`, this change will cause a `valueChanges` event on the `FormArray` + * to be emitted. This defaults to true (as it falls through to `updateValueAndValidity`). */ patchValue(value: any[], options: {onlySelf?: boolean, emitEvent?: boolean} = {}): void { value.forEach((newValue: any, index: number) => { @@ -1441,6 +1699,7 @@ export class FormArray extends AbstractControl { } /** + * @description * Resets the `FormArray`. This means by default: * * * The array and all descendants are marked `pristine` @@ -1451,15 +1710,19 @@ export class FormArray extends AbstractControl { * that matches the structure of the control. The state can be a standalone value * or a form state object with both a value and a disabled status. * - * ### Example + * ### Reset the values in a form array * * ```ts - * this.arr.reset(['name', 'last name']); + * const arr = new FormArray([ + * new FormControl(), + * new FormControl() + * ]); + * arr.reset(['name', 'last name']); * * console.log(this.arr.value); // ['name', 'last name'] * ``` * - * - OR - + * ### Reset the values in a form array and the disabled status for the first control * * ``` * this.arr.reset([ @@ -1470,6 +1733,15 @@ export class FormArray extends AbstractControl { * console.log(this.arr.value); // ['name', 'last name'] * console.log(this.arr.get(0).status); // 'DISABLED' * ``` + * + * @param value Array of latest values for the controls + * @param options Configure options for emitting events when the control value changes + * + * * If `onlySelf` is `true`, this change will only affect the validation of this `FormArray` + * and not its parent component. This defaults to false. + * + * * If `emitEvent` is `true`, this change will cause a `valueChanges` event on the `FormArray` + * to be emitted. This defaults to true (as it falls through to `updateValueAndValidity`). */ reset(value: any = [], options: {onlySelf?: boolean, emitEvent?: boolean} = {}): void { this._forEachChild((control: AbstractControl, index: number) => { @@ -1481,6 +1753,7 @@ export class FormArray extends AbstractControl { } /** + * @description * The aggregate value of the array, including any disabled controls. * * If you'd like to include all values regardless of disabled status, use this method.