/** * @license * Copyright Google LLC 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 (options).asyncValidators !== undefined || (options).validators !== undefined || (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. * * * */ 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); } } }