docs(forms): update reactive form directives API reference (#26823)
PR Close #26823
This commit is contained in:
parent
6744b19297
commit
099d1a67a0
|
@ -30,38 +30,17 @@ export const formControlBinding: any = {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @description
|
* @description
|
||||||
|
* * Syncs a standalone `FormControl` instance to a form control element.
|
||||||
*
|
*
|
||||||
* Syncs a standalone `FormControl` instance to a form control element.
|
* @see [Reactive Forms Guide](guide/reactive-forms)
|
||||||
*
|
* @see `FormControl`
|
||||||
* This directive ensures that any values written to the `FormControl`
|
* @see `AbstractControl`
|
||||||
* instance programmatically will be written to the DOM element (model -> view). Conversely,
|
|
||||||
* any values written to the DOM element through user input will be reflected in the
|
|
||||||
* `FormControl` instance (view -> model).
|
|
||||||
*
|
*
|
||||||
* @usageNotes
|
* @usageNotes
|
||||||
* Use this directive if you'd like to create and manage a `FormControl` instance directly.
|
|
||||||
* Simply create a `FormControl`, save it to your component class, and pass it into the
|
|
||||||
* `FormControlDirective`.
|
|
||||||
*
|
*
|
||||||
* This directive is designed to be used as a standalone control. Unlike `FormControlName`,
|
* ### Registering a single form control
|
||||||
* it does not require that your `FormControl` instance be part of any parent
|
|
||||||
* `FormGroup`, and it won't be registered to any `FormGroupDirective` that
|
|
||||||
* exists above it.
|
|
||||||
*
|
*
|
||||||
* **Get the value**: the `value` property is always synced and available on the
|
* The following examples shows how to register a standalone control and set its value.
|
||||||
* `FormControl` instance. See a full list of available properties in
|
|
||||||
* `AbstractControl`.
|
|
||||||
*
|
|
||||||
* **Set the value**: You can pass in an initial value when instantiating the `FormControl`,
|
|
||||||
* or you can set it programmatically later using {@link AbstractControl#setValue setValue} or
|
|
||||||
* {@link AbstractControl#patchValue patchValue}.
|
|
||||||
*
|
|
||||||
* **Listen to value**: If you want to listen to changes in the value of the control, you can
|
|
||||||
* subscribe to the {@link AbstractControl#valueChanges valueChanges} event. You can also listen to
|
|
||||||
* {@link AbstractControl#statusChanges statusChanges} to be notified when the validation status is
|
|
||||||
* re-calculated.
|
|
||||||
*
|
|
||||||
* ### Example
|
|
||||||
*
|
*
|
||||||
* {@example forms/ts/simpleFormControl/simple_form_control_example.ts region='Component'}
|
* {@example forms/ts/simpleFormControl/simple_form_control_example.ts region='Component'}
|
||||||
*
|
*
|
||||||
|
@ -138,11 +117,23 @@ export const formControlBinding: any = {
|
||||||
@Directive({selector: '[formControl]', providers: [formControlBinding], exportAs: 'ngForm'})
|
@Directive({selector: '[formControl]', providers: [formControlBinding], exportAs: 'ngForm'})
|
||||||
|
|
||||||
export class FormControlDirective extends NgControl implements OnChanges {
|
export class FormControlDirective extends NgControl implements OnChanges {
|
||||||
|
/**
|
||||||
|
* @description
|
||||||
|
* Internal reference to the view model value.
|
||||||
|
*/
|
||||||
viewModel: any;
|
viewModel: any;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description
|
||||||
|
* Tracks the `FormControl` instance bound to the directive.
|
||||||
|
*/
|
||||||
// TODO(issue/24571): remove '!'.
|
// TODO(issue/24571): remove '!'.
|
||||||
@Input('formControl') form !: FormControl;
|
@Input('formControl') form !: FormControl;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description
|
||||||
|
* Triggers a warning that this input should not be used with reactive forms.
|
||||||
|
*/
|
||||||
@Input('disabled')
|
@Input('disabled')
|
||||||
set isDisabled(isDisabled: boolean) { ReactiveErrors.disabledAttrWarning(); }
|
set isDisabled(isDisabled: boolean) { ReactiveErrors.disabledAttrWarning(); }
|
||||||
|
|
||||||
|
@ -155,6 +146,7 @@ export class FormControlDirective extends NgControl implements OnChanges {
|
||||||
@Output('ngModelChange') update = new EventEmitter();
|
@Output('ngModelChange') update = new EventEmitter();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @description
|
||||||
* Static property used to track whether any ngModel warnings have been sent across
|
* Static property used to track whether any ngModel warnings have been sent across
|
||||||
* all instances of FormControlDirective. Used to support warning config of "once".
|
* all instances of FormControlDirective. Used to support warning config of "once".
|
||||||
*
|
*
|
||||||
|
@ -163,8 +155,9 @@ export class FormControlDirective extends NgControl implements OnChanges {
|
||||||
static _ngModelWarningSentOnce = false;
|
static _ngModelWarningSentOnce = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @description
|
||||||
* Instance property used to track whether an ngModel warning has been sent out for this
|
* Instance property used to track whether an ngModel warning has been sent out for this
|
||||||
* particular FormControlDirective instance. Used to support warning config of "always".
|
* particular `FormControlDirective` instance. Used to support warning config of "always".
|
||||||
*
|
*
|
||||||
* @internal
|
* @internal
|
||||||
*/
|
*/
|
||||||
|
@ -181,6 +174,13 @@ export class FormControlDirective extends NgControl implements OnChanges {
|
||||||
this.valueAccessor = selectValueAccessor(this, valueAccessors);
|
this.valueAccessor = selectValueAccessor(this, valueAccessors);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description
|
||||||
|
* A lifecycle method called when the directive's inputs change. For internal use
|
||||||
|
* only.
|
||||||
|
*
|
||||||
|
* @param changes A object of key/value pairs for the set of changed inputs.
|
||||||
|
*/
|
||||||
ngOnChanges(changes: SimpleChanges): void {
|
ngOnChanges(changes: SimpleChanges): void {
|
||||||
if (this._isControlChanged(changes)) {
|
if (this._isControlChanged(changes)) {
|
||||||
setUpControl(this.form, this);
|
setUpControl(this.form, this);
|
||||||
|
@ -197,16 +197,41 @@ export class FormControlDirective extends NgControl implements OnChanges {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description
|
||||||
|
* Returns an array that represents the path from the top-level form to this control.
|
||||||
|
* Each index is the string name of the control on that level.
|
||||||
|
*/
|
||||||
get path(): string[] { return []; }
|
get path(): string[] { return []; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description
|
||||||
|
* Synchronous validator function composed of all the synchronous validators
|
||||||
|
* registered with this directive.
|
||||||
|
*/
|
||||||
get validator(): ValidatorFn|null { return composeValidators(this._rawValidators); }
|
get validator(): ValidatorFn|null { return composeValidators(this._rawValidators); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description
|
||||||
|
* Async validator function composed of all the async validators registered with this
|
||||||
|
* directive.
|
||||||
|
*/
|
||||||
get asyncValidator(): AsyncValidatorFn|null {
|
get asyncValidator(): AsyncValidatorFn|null {
|
||||||
return composeAsyncValidators(this._rawAsyncValidators);
|
return composeAsyncValidators(this._rawAsyncValidators);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description
|
||||||
|
* The `FormControl` bound to this directive.
|
||||||
|
*/
|
||||||
get control(): FormControl { return this.form; }
|
get control(): FormControl { return this.form; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description
|
||||||
|
* Sets the new value for the view model and emits an `ngModelChange` event.
|
||||||
|
*
|
||||||
|
* @param newValue The new value for the view model.
|
||||||
|
*/
|
||||||
viewToModelUpdate(newValue: any): void {
|
viewToModelUpdate(newValue: any): void {
|
||||||
this.viewModel = newValue;
|
this.viewModel = newValue;
|
||||||
this.update.emit(newValue);
|
this.update.emit(newValue);
|
||||||
|
|
|
@ -29,42 +29,19 @@ export const controlNameBinding: any = {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @description
|
* @description
|
||||||
*
|
|
||||||
* Syncs a `FormControl` in an existing `FormGroup` to a form control
|
* Syncs a `FormControl` in an existing `FormGroup` to a form control
|
||||||
* element by name.
|
* element by name.
|
||||||
*
|
*
|
||||||
* This directive ensures that any values written to the `FormControl`
|
* @see [Reactive Forms Guide](guide/reactive-forms)
|
||||||
* instance programmatically will be written to the DOM element (model -> view). Conversely,
|
* @see `FormControl`
|
||||||
* any values written to the DOM element through user input will be reflected in the
|
* @see `AbstractControl`
|
||||||
* `FormControl` instance (view -> model).
|
|
||||||
*
|
*
|
||||||
* @usageNotes
|
* @usageNotes
|
||||||
* This directive is designed to be used with a parent `FormGroupDirective` (selector:
|
|
||||||
* `[formGroup]`).
|
|
||||||
*
|
*
|
||||||
* It accepts the string name of the `FormControl` instance you want to
|
* ### Register `FormControl` within a group
|
||||||
* link, and will look for a `FormControl` registered with that name in the
|
|
||||||
* closest `FormGroup` or `FormArray` above it.
|
|
||||||
*
|
*
|
||||||
* **Access the control**: You can access the `FormControl` associated with
|
* The following example shows how to register multiple form controls within a form group
|
||||||
* this directive by using the {@link AbstractControl#get get} method.
|
* and set their value.
|
||||||
* Ex: `this.form.get('first');`
|
|
||||||
*
|
|
||||||
* **Get value**: the `value` property is always synced and available on the `FormControl`.
|
|
||||||
* See a full list of available properties in `AbstractControl`.
|
|
||||||
*
|
|
||||||
* **Set value**: You can set an initial value for the control when instantiating the
|
|
||||||
* `FormControl`, or you can set it programmatically later using
|
|
||||||
* {@link AbstractControl#setValue setValue} or {@link AbstractControl#patchValue patchValue}.
|
|
||||||
*
|
|
||||||
* **Listen to value**: If you want to listen to changes in the value of the control, you can
|
|
||||||
* subscribe to the {@link AbstractControl#valueChanges valueChanges} event. You can also listen to
|
|
||||||
* {@link AbstractControl#statusChanges statusChanges} to be notified when the validation status is
|
|
||||||
* re-calculated.
|
|
||||||
*
|
|
||||||
* ### Example
|
|
||||||
*
|
|
||||||
* In this example, we create form controls for first name and last name.
|
|
||||||
*
|
*
|
||||||
* {@example forms/ts/simpleFormGroup/simple_form_group_example.ts region='Component'}
|
* {@example forms/ts/simpleFormGroup/simple_form_group_example.ts region='Component'}
|
||||||
*
|
*
|
||||||
|
@ -150,14 +127,32 @@ export const controlNameBinding: any = {
|
||||||
@Directive({selector: '[formControlName]', providers: [controlNameBinding]})
|
@Directive({selector: '[formControlName]', providers: [controlNameBinding]})
|
||||||
export class FormControlName extends NgControl implements OnChanges, OnDestroy {
|
export class FormControlName extends NgControl implements OnChanges, OnDestroy {
|
||||||
private _added = false;
|
private _added = false;
|
||||||
/** @internal */
|
/**
|
||||||
|
* @description
|
||||||
|
* Internal reference to the view model value.
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
viewModel: any;
|
viewModel: any;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description
|
||||||
|
* Tracks the `FormControl` instance bound to the directive.
|
||||||
|
*/
|
||||||
// TODO(issue/24571): remove '!'.
|
// TODO(issue/24571): remove '!'.
|
||||||
readonly control !: FormControl;
|
readonly control !: FormControl;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description
|
||||||
|
* Tracks the name of the `FormControl` bound to the directive. The name corresponds
|
||||||
|
* to a key in the parent `FormGroup` or `FormArray`.
|
||||||
|
*/
|
||||||
// TODO(issue/24571): remove '!'.
|
// TODO(issue/24571): remove '!'.
|
||||||
@Input('formControlName') name !: string;
|
@Input('formControlName') name !: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description
|
||||||
|
* Triggers a warning that this input should not be used with reactive forms.
|
||||||
|
*/
|
||||||
@Input('disabled')
|
@Input('disabled')
|
||||||
set isDisabled(isDisabled: boolean) { ReactiveErrors.disabledAttrWarning(); }
|
set isDisabled(isDisabled: boolean) { ReactiveErrors.disabledAttrWarning(); }
|
||||||
|
|
||||||
|
@ -170,6 +165,7 @@ export class FormControlName extends NgControl implements OnChanges, OnDestroy {
|
||||||
@Output('ngModelChange') update = new EventEmitter();
|
@Output('ngModelChange') update = new EventEmitter();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @description
|
||||||
* Static property used to track whether any ngModel warnings have been sent across
|
* Static property used to track whether any ngModel warnings have been sent across
|
||||||
* all instances of FormControlName. Used to support warning config of "once".
|
* all instances of FormControlName. Used to support warning config of "once".
|
||||||
*
|
*
|
||||||
|
@ -178,6 +174,7 @@ export class FormControlName extends NgControl implements OnChanges, OnDestroy {
|
||||||
static _ngModelWarningSentOnce = false;
|
static _ngModelWarningSentOnce = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @description
|
||||||
* Instance property used to track whether an ngModel warning has been sent out for this
|
* Instance property used to track whether an ngModel warning has been sent out for this
|
||||||
* particular FormControlName instance. Used to support warning config of "always".
|
* particular FormControlName instance. Used to support warning config of "always".
|
||||||
*
|
*
|
||||||
|
@ -200,6 +197,12 @@ export class FormControlName extends NgControl implements OnChanges, OnDestroy {
|
||||||
this.valueAccessor = selectValueAccessor(this, valueAccessors);
|
this.valueAccessor = selectValueAccessor(this, valueAccessors);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description
|
||||||
|
* A lifecycle method called when the directive's inputs change. For internal use only.
|
||||||
|
*
|
||||||
|
* @param changes A object of key/value pairs for the set of changed inputs.
|
||||||
|
*/
|
||||||
ngOnChanges(changes: SimpleChanges) {
|
ngOnChanges(changes: SimpleChanges) {
|
||||||
if (!this._added) this._setUpControl();
|
if (!this._added) this._setUpControl();
|
||||||
if (isPropertyUpdated(changes, this.viewModel)) {
|
if (isPropertyUpdated(changes, this.viewModel)) {
|
||||||
|
@ -209,23 +212,54 @@ export class FormControlName extends NgControl implements OnChanges, OnDestroy {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description
|
||||||
|
* Lifecycle method called before the directive's instance is destroyed. For internal use only.
|
||||||
|
*
|
||||||
|
* @param changes A object of key/value pairs for the set of changed inputs.
|
||||||
|
*/
|
||||||
ngOnDestroy(): void {
|
ngOnDestroy(): void {
|
||||||
if (this.formDirective) {
|
if (this.formDirective) {
|
||||||
this.formDirective.removeControl(this);
|
this.formDirective.removeControl(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description
|
||||||
|
* Sets the new value for the view model and emits an `ngModelChange` event.
|
||||||
|
*
|
||||||
|
* @param newValue The new value for the view model.
|
||||||
|
*/
|
||||||
viewToModelUpdate(newValue: any): void {
|
viewToModelUpdate(newValue: any): void {
|
||||||
this.viewModel = newValue;
|
this.viewModel = newValue;
|
||||||
this.update.emit(newValue);
|
this.update.emit(newValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description
|
||||||
|
* Returns an array that represents the path from the top-level form to this control.
|
||||||
|
* Each index is the string name of the control on that level.
|
||||||
|
*/
|
||||||
get path(): string[] { return controlPath(this.name, this._parent !); }
|
get path(): string[] { return controlPath(this.name, this._parent !); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description
|
||||||
|
* The top-level directive for this group if present, otherwise null.
|
||||||
|
*/
|
||||||
get formDirective(): any { return this._parent ? this._parent.formDirective : null; }
|
get formDirective(): any { return this._parent ? this._parent.formDirective : null; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description
|
||||||
|
* Synchronous validator function composed of all the synchronous validators
|
||||||
|
* registered with this directive.
|
||||||
|
*/
|
||||||
get validator(): ValidatorFn|null { return composeValidators(this._rawValidators); }
|
get validator(): ValidatorFn|null { return composeValidators(this._rawValidators); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description
|
||||||
|
* Async validator function composed of all the async validators registered with this
|
||||||
|
* directive.
|
||||||
|
*/
|
||||||
get asyncValidator(): AsyncValidatorFn {
|
get asyncValidator(): AsyncValidatorFn {
|
||||||
return composeAsyncValidators(this._rawAsyncValidators) !;
|
return composeAsyncValidators(this._rawAsyncValidators) !;
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,24 +32,13 @@ export const formDirectiveProvider: any = {
|
||||||
* and `FormArray` instances to child `FormControlName`, `FormGroupName`,
|
* and `FormArray` instances to child `FormControlName`, `FormGroupName`,
|
||||||
* and `FormArrayName` directives.
|
* and `FormArrayName` directives.
|
||||||
*
|
*
|
||||||
* @usageNotes
|
* @see [Reactive Forms Guide](guide/reactive-forms)
|
||||||
* **Set value**: You can set the form's initial value when instantiating the
|
* @see `AbstractControl`
|
||||||
* `FormGroup`, or you can set it programmatically later using the `FormGroup`'s
|
|
||||||
* {@link AbstractControl#setValue setValue} or {@link AbstractControl#patchValue patchValue}
|
|
||||||
* methods.
|
|
||||||
*
|
*
|
||||||
* **Listen to value**: If you want to listen to changes in the value of the form, you can subscribe
|
* ### Register Form Group
|
||||||
* to the `FormGroup`'s {@link AbstractControl#valueChanges valueChanges} event. You can also
|
|
||||||
* listen to its {@link AbstractControl#statusChanges statusChanges} event to be notified when the
|
|
||||||
* validation status is re-calculated.
|
|
||||||
*
|
*
|
||||||
* Furthermore, you can listen to the directive's `ngSubmit` event to be notified when the user has
|
* The following example registers a `FormGroup` with first name and last name controls,
|
||||||
* triggered a form submission. The `ngSubmit` event will be emitted with the original form
|
* and listens for the *ngSubmit* event when the button is clicked.
|
||||||
* submission event.
|
|
||||||
*
|
|
||||||
* ### Example
|
|
||||||
*
|
|
||||||
* In this example, we create form controls for first name and last name.
|
|
||||||
*
|
*
|
||||||
* {@example forms/ts/simpleFormGroup/simple_form_group_example.ts region='Component'}
|
* {@example forms/ts/simpleFormGroup/simple_form_group_example.ts region='Component'}
|
||||||
*
|
*
|
||||||
|
@ -64,13 +53,31 @@ export const formDirectiveProvider: any = {
|
||||||
})
|
})
|
||||||
export class FormGroupDirective extends ControlContainer implements Form,
|
export class FormGroupDirective extends ControlContainer implements Form,
|
||||||
OnChanges {
|
OnChanges {
|
||||||
|
/**
|
||||||
|
* @description
|
||||||
|
* Reports whether the form submission has been triggered.
|
||||||
|
*/
|
||||||
public readonly submitted: boolean = false;
|
public readonly submitted: boolean = false;
|
||||||
|
|
||||||
// TODO(issue/24571): remove '!'.
|
// TODO(issue/24571): remove '!'.
|
||||||
private _oldForm !: FormGroup;
|
private _oldForm !: FormGroup;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description
|
||||||
|
* Tracks the list of added `FormControlName` instances
|
||||||
|
*/
|
||||||
directives: FormControlName[] = [];
|
directives: FormControlName[] = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description
|
||||||
|
* Tracks the `FormGroup` bound to this directive.
|
||||||
|
*/
|
||||||
@Input('formGroup') form: FormGroup = null !;
|
@Input('formGroup') form: FormGroup = null !;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description
|
||||||
|
* Emits an event when the form submission has been triggered.
|
||||||
|
*/
|
||||||
@Output() ngSubmit = new EventEmitter();
|
@Output() ngSubmit = new EventEmitter();
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
|
@ -79,6 +86,12 @@ export class FormGroupDirective extends ControlContainer implements Form,
|
||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description
|
||||||
|
* A lifecycle method called when the directive's inputs change. For internal use only.
|
||||||
|
*
|
||||||
|
* @param changes A object of key/value pairs for the set of changed inputs.
|
||||||
|
*/
|
||||||
ngOnChanges(changes: SimpleChanges): void {
|
ngOnChanges(changes: SimpleChanges): void {
|
||||||
this._checkFormPresent();
|
this._checkFormPresent();
|
||||||
if (changes.hasOwnProperty('form')) {
|
if (changes.hasOwnProperty('form')) {
|
||||||
|
@ -88,12 +101,32 @@ export class FormGroupDirective extends ControlContainer implements Form,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description
|
||||||
|
* Returns this directive's instance.
|
||||||
|
*/
|
||||||
get formDirective(): Form { return this; }
|
get formDirective(): Form { return this; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description
|
||||||
|
* Returns the `FormGroup` bound to this directive.
|
||||||
|
*/
|
||||||
get control(): FormGroup { return this.form; }
|
get control(): FormGroup { return this.form; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description
|
||||||
|
* Returns an array representing the path to this group. Because this directive
|
||||||
|
* always lives at the top level of a form, it always an empty array.
|
||||||
|
*/
|
||||||
get path(): string[] { return []; }
|
get path(): string[] { return []; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description
|
||||||
|
* Method that sets up the control directive in this group, re-calculates its value
|
||||||
|
* and validity, and adds the instance to the internal list of directives.
|
||||||
|
*
|
||||||
|
* @param dir The `FormControlName` directive instance.
|
||||||
|
*/
|
||||||
addControl(dir: FormControlName): FormControl {
|
addControl(dir: FormControlName): FormControl {
|
||||||
const ctrl: any = this.form.get(dir.path);
|
const ctrl: any = this.form.get(dir.path);
|
||||||
setUpControl(ctrl, dir);
|
setUpControl(ctrl, dir);
|
||||||
|
@ -102,35 +135,92 @@ export class FormGroupDirective extends ControlContainer implements Form,
|
||||||
return ctrl;
|
return ctrl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description
|
||||||
|
* Retrieves the `FormControl` instance from the provided `FormControlName` directive
|
||||||
|
*
|
||||||
|
* @param dir The `FormControlName` directive instance.
|
||||||
|
*/
|
||||||
getControl(dir: FormControlName): FormControl { return <FormControl>this.form.get(dir.path); }
|
getControl(dir: FormControlName): FormControl { return <FormControl>this.form.get(dir.path); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description
|
||||||
|
* Removes the `FormControlName` instance from the internal list of directives
|
||||||
|
*
|
||||||
|
* @param dir The `FormControlName` directive instance.
|
||||||
|
*/
|
||||||
removeControl(dir: FormControlName): void { removeDir<FormControlName>(this.directives, dir); }
|
removeControl(dir: FormControlName): void { removeDir<FormControlName>(this.directives, dir); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a new `FormGroupName` directive instance to the form.
|
||||||
|
*
|
||||||
|
* @param dir The `FormGroupName` directive instance.
|
||||||
|
*/
|
||||||
addFormGroup(dir: FormGroupName): void {
|
addFormGroup(dir: FormGroupName): void {
|
||||||
const ctrl: any = this.form.get(dir.path);
|
const ctrl: any = this.form.get(dir.path);
|
||||||
setUpFormContainer(ctrl, dir);
|
setUpFormContainer(ctrl, dir);
|
||||||
ctrl.updateValueAndValidity({emitEvent: false});
|
ctrl.updateValueAndValidity({emitEvent: false});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* No-op method to remove the form group.
|
||||||
|
*
|
||||||
|
* @param dir The `FormGroupName` directive instance.
|
||||||
|
*/
|
||||||
removeFormGroup(dir: FormGroupName): void {}
|
removeFormGroup(dir: FormGroupName): void {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description
|
||||||
|
* Retrieves the `FormGroup` for a provided `FormGroupName` directive instance
|
||||||
|
*
|
||||||
|
* @param dir The `FormGroupName` directive instance.
|
||||||
|
*/
|
||||||
getFormGroup(dir: FormGroupName): FormGroup { return <FormGroup>this.form.get(dir.path); }
|
getFormGroup(dir: FormGroupName): FormGroup { return <FormGroup>this.form.get(dir.path); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a new `FormArrayName` directive instance to the form.
|
||||||
|
*
|
||||||
|
* @param dir The `FormArrayName` directive instance.
|
||||||
|
*/
|
||||||
addFormArray(dir: FormArrayName): void {
|
addFormArray(dir: FormArrayName): void {
|
||||||
const ctrl: any = this.form.get(dir.path);
|
const ctrl: any = this.form.get(dir.path);
|
||||||
setUpFormContainer(ctrl, dir);
|
setUpFormContainer(ctrl, dir);
|
||||||
ctrl.updateValueAndValidity({emitEvent: false});
|
ctrl.updateValueAndValidity({emitEvent: false});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* No-op method to remove the form array.
|
||||||
|
*
|
||||||
|
* @param dir The `FormArrayName` directive instance.
|
||||||
|
*/
|
||||||
removeFormArray(dir: FormArrayName): void {}
|
removeFormArray(dir: FormArrayName): void {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description
|
||||||
|
* Retrieves the `FormArray` for a provided `FormArrayName` directive instance.
|
||||||
|
*
|
||||||
|
* @param dir The `FormArrayName` directive instance.
|
||||||
|
*/
|
||||||
getFormArray(dir: FormArrayName): FormArray { return <FormArray>this.form.get(dir.path); }
|
getFormArray(dir: FormArrayName): FormArray { return <FormArray>this.form.get(dir.path); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the new value for the provided `FormControlName` directive.
|
||||||
|
*
|
||||||
|
* @param dir The `FormControlName` directive instance.
|
||||||
|
* @param value The new value for the directive's control.
|
||||||
|
*/
|
||||||
updateModel(dir: FormControlName, value: any): void {
|
updateModel(dir: FormControlName, value: any): void {
|
||||||
const ctrl = <FormControl>this.form.get(dir.path);
|
const ctrl = <FormControl>this.form.get(dir.path);
|
||||||
ctrl.setValue(value);
|
ctrl.setValue(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description
|
||||||
|
* Method called with the "submit" event is triggered on the form.
|
||||||
|
* Triggers the `ngSubmit` emitter to emit the "submit" event as its payload.
|
||||||
|
*
|
||||||
|
* @param $event The "submit" event object
|
||||||
|
*/
|
||||||
onSubmit($event: Event): boolean {
|
onSubmit($event: Event): boolean {
|
||||||
(this as{submitted: boolean}).submitted = true;
|
(this as{submitted: boolean}).submitted = true;
|
||||||
syncPendingControls(this.form, this.directives);
|
syncPendingControls(this.form, this.directives);
|
||||||
|
@ -138,8 +228,18 @@ export class FormGroupDirective extends ControlContainer implements Form,
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description
|
||||||
|
* Method called when the "reset" event is triggered on the form.
|
||||||
|
*/
|
||||||
onReset(): void { this.resetForm(); }
|
onReset(): void { this.resetForm(); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description
|
||||||
|
* Resets the form to an initial value and resets its submitted status.
|
||||||
|
*
|
||||||
|
* @param value The new value for the form.
|
||||||
|
*/
|
||||||
resetForm(value: any = undefined): void {
|
resetForm(value: any = undefined): void {
|
||||||
this.form.reset(value);
|
this.form.reset(value);
|
||||||
(this as{submitted: boolean}).submitted = false;
|
(this as{submitted: boolean}).submitted = false;
|
||||||
|
|
|
@ -28,37 +28,42 @@ export const formGroupNameProvider: any = {
|
||||||
*
|
*
|
||||||
* Syncs a nested `FormGroup` to a DOM element.
|
* Syncs a nested `FormGroup` to a DOM element.
|
||||||
*
|
*
|
||||||
* This directive can only be used with a parent `FormGroupDirective` (selector:
|
* This directive can only be used with a parent `FormGroupDirective`.
|
||||||
* `[formGroup]`).
|
|
||||||
*
|
*
|
||||||
* It accepts the string name of the nested `FormGroup` you want to link, and
|
* It accepts the string name of the nested `FormGroup` to link, and
|
||||||
* will look for a `FormGroup` registered with that name in the parent
|
* looks for a `FormGroup` registered with that name in the parent
|
||||||
* `FormGroup` instance you passed into `FormGroupDirective`.
|
* `FormGroup` instance you passed into `FormGroupDirective`.
|
||||||
*
|
*
|
||||||
* Nested form groups can come in handy when you want to validate a sub-group of a
|
* Use nested form groups to validate a sub-group of a
|
||||||
* form separately from the rest or when you'd like to group the values of certain
|
* form separately from the rest or to group the values of certain
|
||||||
* controls into their own nested object.
|
* controls into their own nested object.
|
||||||
*
|
*
|
||||||
|
* @see [Reactive Forms Guide](guide/reactive-forms)
|
||||||
|
*
|
||||||
* @usageNotes
|
* @usageNotes
|
||||||
* **Access the group**: You can access the associated `FormGroup` using the
|
|
||||||
* {@link AbstractControl#get get} method. Ex: `this.form.get('name')`.
|
|
||||||
*
|
*
|
||||||
* You can also access individual controls within the group using dot syntax.
|
* ### Access the group by name
|
||||||
* Ex: `this.form.get('name.first')`
|
|
||||||
*
|
*
|
||||||
* **Get the value**: the `value` property is always synced and available on the
|
* The following example uses the {@link AbstractControl#get get} method to access the
|
||||||
* `FormGroup`. See a full list of available properties in `AbstractControl`.
|
* associated `FormGroup`
|
||||||
*
|
*
|
||||||
* **Set the value**: You can set an initial value for each child control when instantiating
|
* ```ts
|
||||||
* the `FormGroup`, or you can set it programmatically later using
|
* this.form.get('name');
|
||||||
* {@link AbstractControl#setValue setValue} or {@link AbstractControl#patchValue patchValue}.
|
* ```
|
||||||
*
|
*
|
||||||
* **Listen to value**: If you want to listen to changes in the value of the group, you can
|
* ### Access individual controls in the group
|
||||||
* subscribe to the {@link AbstractControl#valueChanges valueChanges} event. You can also listen to
|
|
||||||
* {@link AbstractControl#statusChanges statusChanges} to be notified when the validation status is
|
|
||||||
* re-calculated.
|
|
||||||
*
|
*
|
||||||
* ### Example
|
* The following example uses the {@link AbstractControl#get get} method to access
|
||||||
|
* individual controls within the group using dot syntax.
|
||||||
|
*
|
||||||
|
* ```ts
|
||||||
|
* this.form.get('name.first');
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* ### Register a nested `FormGroup`.
|
||||||
|
*
|
||||||
|
* The following example registers a nested *name* `FormGroup` within an existing `FormGroup`,
|
||||||
|
* and provides methods to retrieve the nested `FormGroup` and individual controls.
|
||||||
*
|
*
|
||||||
* {@example forms/ts/nestedFormGroup/nested_form_group_example.ts region='Component'}
|
* {@example forms/ts/nestedFormGroup/nested_form_group_example.ts region='Component'}
|
||||||
*
|
*
|
||||||
|
@ -67,6 +72,11 @@ export const formGroupNameProvider: any = {
|
||||||
*/
|
*/
|
||||||
@Directive({selector: '[formGroupName]', providers: [formGroupNameProvider]})
|
@Directive({selector: '[formGroupName]', providers: [formGroupNameProvider]})
|
||||||
export class FormGroupName extends AbstractFormGroupDirective implements OnInit, OnDestroy {
|
export class FormGroupName extends AbstractFormGroupDirective implements OnInit, OnDestroy {
|
||||||
|
/**
|
||||||
|
* @description
|
||||||
|
* Tracks the name of the `FormGroup` bound to the directive. The name corresponds
|
||||||
|
* to a key in the parent `FormGroup` or `FormArray`.
|
||||||
|
*/
|
||||||
// TODO(issue/24571): remove '!'.
|
// TODO(issue/24571): remove '!'.
|
||||||
@Input('formGroupName') name !: string;
|
@Input('formGroupName') name !: string;
|
||||||
|
|
||||||
|
@ -105,31 +115,10 @@ export const formArrayNameProvider: any = {
|
||||||
* will look for a `FormArray` registered with that name in the parent
|
* will look for a `FormArray` registered with that name in the parent
|
||||||
* `FormGroup` instance you passed into `FormGroupDirective`.
|
* `FormGroup` instance you passed into `FormGroupDirective`.
|
||||||
*
|
*
|
||||||
* Nested form arrays can come in handy when you have a group of form controls but
|
* @see [Reactive Forms Guide](guide/reactive-forms)
|
||||||
* you're not sure how many there will be. Form arrays allow you to create new
|
* @see `AbstractControl`
|
||||||
* form controls dynamically.
|
|
||||||
*
|
*
|
||||||
* @usageNotes
|
* @usageNotes
|
||||||
* **Access the array**: You can access the associated `FormArray` using the
|
|
||||||
* {@link AbstractControl#get get} method on the parent `FormGroup`.
|
|
||||||
* Ex: `this.form.get('cities')`.
|
|
||||||
*
|
|
||||||
* **Get the value**: the `value` property is always synced and available on the
|
|
||||||
* `FormArray`. See a full list of available properties in `AbstractControl`.
|
|
||||||
*
|
|
||||||
* **Set the value**: You can set an initial value for each child control when instantiating
|
|
||||||
* the `FormArray`, or you can set the value programmatically later using the
|
|
||||||
* `FormArray`'s {@link AbstractControl#setValue setValue} or
|
|
||||||
* {@link AbstractControl#patchValue patchValue} methods.
|
|
||||||
*
|
|
||||||
* **Listen to value**: If you want to listen to changes in the value of the array, you can
|
|
||||||
* subscribe to the `FormArray`'s {@link AbstractControl#valueChanges valueChanges} event.
|
|
||||||
* You can also listen to its {@link AbstractControl#statusChanges statusChanges} event to be
|
|
||||||
* notified when the validation status is re-calculated.
|
|
||||||
*
|
|
||||||
* **Add new controls**: You can add new controls to the `FormArray` dynamically by calling
|
|
||||||
* its {@link FormArray#push push} method.
|
|
||||||
* Ex: `this.form.get('cities').push(new FormControl());`
|
|
||||||
*
|
*
|
||||||
* ### Example
|
* ### Example
|
||||||
*
|
*
|
||||||
|
@ -149,6 +138,11 @@ export class FormArrayName extends ControlContainer implements OnInit, OnDestroy
|
||||||
/** @internal */
|
/** @internal */
|
||||||
_asyncValidators: any[];
|
_asyncValidators: any[];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description
|
||||||
|
* Tracks the name of the `FormArray` bound to the directive. The name corresponds
|
||||||
|
* to a key in the parent `FormGroup` or `FormArray`.
|
||||||
|
*/
|
||||||
// TODO(issue/24571): remove '!'.
|
// TODO(issue/24571): remove '!'.
|
||||||
@Input('formArrayName') name !: string;
|
@Input('formArrayName') name !: string;
|
||||||
|
|
||||||
|
@ -162,27 +156,59 @@ export class FormArrayName extends ControlContainer implements OnInit, OnDestroy
|
||||||
this._asyncValidators = asyncValidators;
|
this._asyncValidators = asyncValidators;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description
|
||||||
|
* A lifecycle method called when the directive's inputs are initialized. For internal use only.
|
||||||
|
*
|
||||||
|
* @throws If the directive does not have a valid parent.
|
||||||
|
*/
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
this._checkParentType();
|
this._checkParentType();
|
||||||
this.formDirective !.addFormArray(this);
|
this.formDirective !.addFormArray(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description
|
||||||
|
* A lifecycle method called before the directive's instance is destroyed. For internal use only.
|
||||||
|
*/
|
||||||
ngOnDestroy(): void {
|
ngOnDestroy(): void {
|
||||||
if (this.formDirective) {
|
if (this.formDirective) {
|
||||||
this.formDirective.removeFormArray(this);
|
this.formDirective.removeFormArray(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description
|
||||||
|
* The `FormArray` bound to this directive.
|
||||||
|
*/
|
||||||
get control(): FormArray { return this.formDirective !.getFormArray(this); }
|
get control(): FormArray { return this.formDirective !.getFormArray(this); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description
|
||||||
|
* The top-level directive for this group if present, otherwise null.
|
||||||
|
*/
|
||||||
get formDirective(): FormGroupDirective|null {
|
get formDirective(): FormGroupDirective|null {
|
||||||
return this._parent ? <FormGroupDirective>this._parent.formDirective : null;
|
return this._parent ? <FormGroupDirective>this._parent.formDirective : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description
|
||||||
|
* Returns an array that represents the path from the top-level form to this control.
|
||||||
|
* Each index is the string name of the control on that level.
|
||||||
|
*/
|
||||||
get path(): string[] { return controlPath(this.name, this._parent); }
|
get path(): string[] { return controlPath(this.name, this._parent); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description
|
||||||
|
* Synchronous validator function composed of all the synchronous validators registered with this
|
||||||
|
* directive.
|
||||||
|
*/
|
||||||
get validator(): ValidatorFn|null { return composeValidators(this._validators); }
|
get validator(): ValidatorFn|null { return composeValidators(this._validators); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description
|
||||||
|
* Async validator function composed of all the async validators registered with this directive.
|
||||||
|
*/
|
||||||
get asyncValidator(): AsyncValidatorFn|null {
|
get asyncValidator(): AsyncValidatorFn|null {
|
||||||
return composeAsyncValidators(this._asyncValidators);
|
return composeAsyncValidators(this._asyncValidators);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue