angular-docs-cn/packages/forms/src/form_builder.ts
Rado Kirov 03d2e5cb1d refactor: Consistently use index access on index signature types. (#28937)
This change helps highlight certain misoptimizations with Closure
compiler. It is also stylistically preferable to consistently use index
access on index sig types.

Roughly, when one sees '.foo' they know it is always checked for typos
in the prop name by the type system (unless 'any'), while "['foo']" is
always not.

Once all angular repos are conforming this will become a tsetse.info
check, enforced by bazel.

PR Close #28937
2019-02-28 02:49:14 -08:00

159 lines
6.1 KiB
TypeScript

/**
* @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
*/
import {Injectable} from '@angular/core';
import {AsyncValidatorFn, ValidatorFn} from './directives/validators';
import {AbstractControl, AbstractControlOptions, FormArray, FormControl, FormGroup, FormHooks} from './model';
function isAbstractControlOptions(options: AbstractControlOptions | {[key: string]: any}):
options is AbstractControlOptions {
return (<AbstractControlOptions>options).asyncValidators !== undefined ||
(<AbstractControlOptions>options).validators !== undefined ||
(<AbstractControlOptions>options).updateOn !== undefined;
}
/**
* @description
* Creates an `AbstractControl` from a user-specified configuration.
*
* The `FormBuilder` provides syntactic sugar that shortens creating instances of a `FormControl`,
* `FormGroup`, or `FormArray`. It reduces the amount of boilerplate needed to build complex
* forms.
*
* @see [Reactive Forms Guide](/guide/reactive-forms)
*
* @publicApi
*/
@Injectable()
export class FormBuilder {
/**
* @description
* Construct a new `FormGroup` instance.
*
* @param controlsConfig A collection of child controls. The key for each child is the name
* under which it is registered.
*
* @param options Configuration options object for the `FormGroup`. The object can
* have two shapes:
*
* 1) `AbstractControlOptions` object (preferred), which consists of:
* * `validators`: A synchronous validator function, or an array of validator functions
* * `asyncValidators`: A single async validator or array of async validator functions
* * `updateOn`: The event upon which the control should be updated (options: 'change' | 'blur' |
* submit')
*
* 2) Legacy configuration object, which consists of:
* * `validator`: A synchronous validator function, or an array of validator functions
* * `asyncValidator`: A single async validator or array of async validator functions
*
*/
group(
controlsConfig: {[key: string]: any},
options: AbstractControlOptions|{[key: string]: any}|null = null): FormGroup {
const controls = this._reduceControls(controlsConfig);
let validators: ValidatorFn|ValidatorFn[]|null = null;
let asyncValidators: AsyncValidatorFn|AsyncValidatorFn[]|null = null;
let updateOn: FormHooks|undefined = undefined;
if (options != null) {
if (isAbstractControlOptions(options)) {
// `options` are `AbstractControlOptions`
validators = options.validators != null ? options.validators : null;
asyncValidators = options.asyncValidators != null ? options.asyncValidators : null;
updateOn = options.updateOn != null ? options.updateOn : undefined;
} else {
// `options` are legacy form group options
validators = options['validator'] != null ? options['validator'] : null;
asyncValidators = options['asyncValidator'] != null ? options['asyncValidator'] : null;
}
}
return new FormGroup(controls, {asyncValidators, updateOn, validators});
}
/**
* @description
* Construct a new `FormControl` with the given state, validators and options.
*
* @param formState Initializes the control with an initial state value, or
* with an object that contains both a value and a disabled status.
*
* @param validatorOrOpts A synchronous validator function, or an array of
* such functions, or an `AbstractControlOptions` object that contains
* validation functions and a validation trigger.
*
* @param asyncValidator A single async validator or array of async validator
* functions.
*
* @usageNotes
*
* ### Initialize a control as disabled
*
* The following example returns a control with an initial value in a disabled state.
*
* <code-example path="forms/ts/formBuilder/form_builder_example.ts"
* linenums="false" region="disabled-control">
* </code-example>
*/
control(
formState: any, validatorOrOpts?: ValidatorFn|ValidatorFn[]|AbstractControlOptions|null,
asyncValidator?: AsyncValidatorFn|AsyncValidatorFn[]|null): FormControl {
return new FormControl(formState, validatorOrOpts, asyncValidator);
}
/**
* Constructs a new `FormArray` from the given array of configurations,
* validators and options.
*
* @param controlsConfig An array of child controls or control configs. Each
* child control is given an index when it is registered.
*
* @param validatorOrOpts A synchronous validator function, or an array of
* such functions, or an `AbstractControlOptions` object that contains
* validation functions and a validation trigger.
*
* @param asyncValidator A single async validator or array of async validator
* functions.
*/
array(
controlsConfig: any[],
validatorOrOpts?: ValidatorFn|ValidatorFn[]|AbstractControlOptions|null,
asyncValidator?: AsyncValidatorFn|AsyncValidatorFn[]|null): FormArray {
const controls = controlsConfig.map(c => this._createControl(c));
return new FormArray(controls, validatorOrOpts, asyncValidator);
}
/** @internal */
_reduceControls(controlsConfig: {[k: string]: any}): {[key: string]: AbstractControl} {
const controls: {[key: string]: AbstractControl} = {};
Object.keys(controlsConfig).forEach(controlName => {
controls[controlName] = this._createControl(controlsConfig[controlName]);
});
return controls;
}
/** @internal */
_createControl(controlConfig: any): AbstractControl {
if (controlConfig instanceof FormControl || controlConfig instanceof FormGroup ||
controlConfig instanceof FormArray) {
return controlConfig;
} else if (Array.isArray(controlConfig)) {
const value = controlConfig[0];
const validator: ValidatorFn = controlConfig.length > 1 ? controlConfig[1] : null;
const asyncValidator: AsyncValidatorFn = controlConfig.length > 2 ? controlConfig[2] : null;
return this.control(value, validator, asyncValidator);
} else {
return this.control(controlConfig);
}
}
}