docs(forms): update API reference for common APIs and template-driven directives (#27033)
PR Close #27033
This commit is contained in:
parent
2389a68ea3
commit
c331fc6f0c
|
@ -26,7 +26,9 @@ function _isAndroid(): boolean {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Turn this mode on if you want form directives to buffer IME input until compositionend
|
* @description
|
||||||
|
* Provide this token to control if form directives buffer IME input until
|
||||||
|
* the "compositionend" event occurs.
|
||||||
* @publicApi
|
* @publicApi
|
||||||
*/
|
*/
|
||||||
export const COMPOSITION_BUFFER_MODE = new InjectionToken<boolean>('CompositionEventMode');
|
export const COMPOSITION_BUFFER_MODE = new InjectionToken<boolean>('CompositionEventMode');
|
||||||
|
|
|
@ -37,9 +37,15 @@ export const ngControlStatusHost = {
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @description
|
||||||
* Directive automatically applied to Angular form controls that sets CSS classes
|
* Directive automatically applied to Angular form controls that sets CSS classes
|
||||||
* based on control status. The following classes are applied as the properties
|
* based on control status.
|
||||||
* become true:
|
*
|
||||||
|
* @usageNotes
|
||||||
|
*
|
||||||
|
* ### CSS classes applied
|
||||||
|
*
|
||||||
|
* The following classes are applied as the properties become true:
|
||||||
*
|
*
|
||||||
* * ng-valid
|
* * ng-valid
|
||||||
* * ng-invalid
|
* * ng-invalid
|
||||||
|
@ -49,8 +55,8 @@ export const ngControlStatusHost = {
|
||||||
* * ng-untouched
|
* * ng-untouched
|
||||||
* * ng-touched
|
* * ng-touched
|
||||||
*
|
*
|
||||||
* @ngModule FormsModule
|
|
||||||
* @ngModule ReactiveFormsModule
|
* @ngModule ReactiveFormsModule
|
||||||
|
* @ngModule FormsModule
|
||||||
* @publicApi
|
* @publicApi
|
||||||
*/
|
*/
|
||||||
@Directive({selector: '[formControlName],[ngModel],[formControl]', host: ngControlStatusHost})
|
@Directive({selector: '[formControlName],[ngModel],[formControl]', host: ngControlStatusHost})
|
||||||
|
@ -59,11 +65,14 @@ export class NgControlStatus extends AbstractControlStatus {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @description
|
||||||
* Directive automatically applied to Angular form groups that sets CSS classes
|
* Directive automatically applied to Angular form groups that sets CSS classes
|
||||||
* based on control status (valid/invalid/dirty/etc).
|
* based on control status (valid/invalid/dirty/etc).
|
||||||
|
*
|
||||||
|
* @see `NgControlStatus`
|
||||||
*
|
*
|
||||||
* @ngModule FormsModule
|
|
||||||
* @ngModule ReactiveFormsModule
|
* @ngModule ReactiveFormsModule
|
||||||
|
* @ngModule FormsModule
|
||||||
* @publicApi
|
* @publicApi
|
||||||
*/
|
*/
|
||||||
@Directive({
|
@Directive({
|
||||||
|
|
|
@ -27,34 +27,36 @@ const resolvedPromise = Promise.resolve(null);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @description
|
* @description
|
||||||
*
|
|
||||||
* Creates a top-level `FormGroup` instance and binds it to a form
|
* Creates a top-level `FormGroup` instance and binds it to a form
|
||||||
* to track aggregate form value and validation status.
|
* to track aggregate form value and validation status.
|
||||||
*
|
*
|
||||||
* As soon as you import the `FormsModule`, this directive becomes active by default on
|
* As soon as you import the `FormsModule`, this directive becomes active by default on
|
||||||
* all `<form>` tags. You don't need to add a special selector.
|
* all `<form>` tags. You don't need to add a special selector.
|
||||||
*
|
*
|
||||||
* You can export the directive into a local template variable using `ngForm` as the key
|
* You optionally export the directive into a local template variable using `ngForm` as the key
|
||||||
* (ex: `#myForm="ngForm"`). This is optional, but useful. Many properties from the underlying
|
* (ex: `#myForm="ngForm"`). This is optional, but useful. Many properties from the underlying
|
||||||
* `FormGroup` instance are duplicated on the directive itself, so a reference to it
|
* `FormGroup` instance are duplicated on the directive itself, so a reference to it
|
||||||
* will give you access to the aggregate value and validity status of the form, as well as
|
* gives you access to the aggregate value and validity status of the form, as well as
|
||||||
* user interaction properties like `dirty` and `touched`.
|
* user interaction properties like `dirty` and `touched`.
|
||||||
*
|
*
|
||||||
* To register child controls with the form, you'll want to use `NgModel` with a
|
* To register child controls with the form, use `NgModel` with a `name`
|
||||||
* `name` attribute. You can also use `NgModelGroup` if you'd like to create
|
* attribute. You may use `NgModelGroup` to create sub-groups within the form.
|
||||||
* sub-groups within the form.
|
|
||||||
*
|
*
|
||||||
* You can listen to the directive's `ngSubmit` event to be notified when the user has
|
* If necessary, listen to the directive's `ngSubmit` event to be notified when the user has
|
||||||
* triggered a form submission. The `ngSubmit` event will be emitted with the original form
|
* triggered a form submission. The `ngSubmit` event emits the original form
|
||||||
* submission event.
|
* submission event.
|
||||||
*
|
*
|
||||||
* In template driven forms, all `<form>` tags are automatically tagged as `NgForm`.
|
* In template driven forms, all `<form>` tags are automatically tagged as `NgForm`.
|
||||||
* If you want to import the `FormsModule` but skip its usage in some forms,
|
* To import the `FormsModule` but skip its usage in some forms,
|
||||||
* for example, to use native HTML5 validation, you can add `ngNoForm` and the `<form>`
|
* for example, to use native HTML5 validation, add the `ngNoForm` and the `<form>`
|
||||||
* tags won't create an `NgForm` directive. In reactive forms, using `ngNoForm` is
|
* tags won't create an `NgForm` directive. In reactive forms, using `ngNoForm` is
|
||||||
* unnecessary because the `<form>` tags are inert. In that case, you would
|
* unnecessary because the `<form>` tags are inert. In that case, you would
|
||||||
* refrain from using the `formGroup` directive.
|
* refrain from using the `formGroup` directive.
|
||||||
*
|
*
|
||||||
|
* @usageNotes
|
||||||
|
*
|
||||||
|
* ### Migrating from deprecated ngForm selector
|
||||||
|
*
|
||||||
* Support for using `ngForm` element selector has been deprecated in Angular v6 and will be removed
|
* Support for using `ngForm` element selector has been deprecated in Angular v6 and will be removed
|
||||||
* in Angular v9.
|
* in Angular v9.
|
||||||
*
|
*
|
||||||
|
@ -71,8 +73,23 @@ const resolvedPromise = Promise.resolve(null);
|
||||||
* <ng-form #myForm="ngForm">
|
* <ng-form #myForm="ngForm">
|
||||||
* ```
|
* ```
|
||||||
*
|
*
|
||||||
|
* ### Listening for form submission
|
||||||
|
*
|
||||||
|
* The following example shows how to capture the form values from the "ngSubmit" event.
|
||||||
|
*
|
||||||
* {@example forms/ts/simpleForm/simple_form_example.ts region='Component'}
|
* {@example forms/ts/simpleForm/simple_form_example.ts region='Component'}
|
||||||
*
|
*
|
||||||
|
* ### Setting the update options
|
||||||
|
*
|
||||||
|
* The following example shows you how to change the "updateOn" option from its default using
|
||||||
|
* ngFormOptions.
|
||||||
|
*
|
||||||
|
* ```html
|
||||||
|
* <form [ngFormOptions]="{updateOn: 'blur'}">
|
||||||
|
* <input name="one" ngModel> <!-- this ngModel will update on blur -->
|
||||||
|
* </form>
|
||||||
|
* ```
|
||||||
|
*
|
||||||
* @ngModule FormsModule
|
* @ngModule FormsModule
|
||||||
* @publicApi
|
* @publicApi
|
||||||
*/
|
*/
|
||||||
|
@ -85,25 +102,33 @@ const resolvedPromise = Promise.resolve(null);
|
||||||
})
|
})
|
||||||
export class NgForm extends ControlContainer implements Form,
|
export class NgForm extends ControlContainer implements Form,
|
||||||
AfterViewInit {
|
AfterViewInit {
|
||||||
|
/**
|
||||||
|
* @description
|
||||||
|
* Returns whether the form submission has been triggered.
|
||||||
|
*/
|
||||||
public readonly submitted: boolean = false;
|
public readonly submitted: boolean = false;
|
||||||
|
|
||||||
private _directives: NgModel[] = [];
|
private _directives: NgModel[] = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description
|
||||||
|
* The `FormGroup` instance created for this form.
|
||||||
|
*/
|
||||||
form: FormGroup;
|
form: FormGroup;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description
|
||||||
|
* Event emitter for the "ngSubmit" event
|
||||||
|
*/
|
||||||
ngSubmit = new EventEmitter();
|
ngSubmit = new EventEmitter();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Options for the `NgForm` instance. Accepts the following properties:
|
* @description
|
||||||
|
* Tracks options for the `NgForm` instance.
|
||||||
*
|
*
|
||||||
* **updateOn**: Serves as the default `updateOn` value for all child `NgModels` below it
|
* **updateOn**: Sets the default `updateOn` value for all child `NgModels` below it
|
||||||
* (unless a child has explicitly set its own value for this in `ngModelOptions`).
|
* unless explicitly set by a child `NgModel` using `ngModelOptions`). Defaults to 'change'.
|
||||||
* Potential values: `'change'` | `'blur'` | `'submit'`
|
* Possible values: `'change'` | `'blur'` | `'submit'`.
|
||||||
*
|
|
||||||
* ```html
|
|
||||||
* <form [ngFormOptions]="{updateOn: 'blur'}">
|
|
||||||
* <input name="one" ngModel> <!-- this ngModel will update on blur -->
|
|
||||||
* </form>
|
|
||||||
* ```
|
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
// TODO(issue/24571): remove '!'.
|
// TODO(issue/24571): remove '!'.
|
||||||
|
@ -117,16 +142,44 @@ export class NgForm extends ControlContainer implements Form,
|
||||||
new FormGroup({}, composeValidators(validators), composeAsyncValidators(asyncValidators));
|
new FormGroup({}, composeValidators(validators), composeAsyncValidators(asyncValidators));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description
|
||||||
|
* Lifecycle method called after the view is initialized. For internal use only.
|
||||||
|
*/
|
||||||
ngAfterViewInit() { this._setUpdateStrategy(); }
|
ngAfterViewInit() { this._setUpdateStrategy(); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description
|
||||||
|
* The directive instance.
|
||||||
|
*/
|
||||||
get formDirective(): Form { return this; }
|
get formDirective(): Form { return this; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description
|
||||||
|
* The internal `FormGroup` instance.
|
||||||
|
*/
|
||||||
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 is always an empty array.
|
||||||
|
*/
|
||||||
get path(): string[] { return []; }
|
get path(): string[] { return []; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description
|
||||||
|
* Returns a map of the controls in this group.
|
||||||
|
*/
|
||||||
get controls(): {[key: string]: AbstractControl} { return this.form.controls; }
|
get controls(): {[key: string]: AbstractControl} { return this.form.controls; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @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 `NgModel` directive instance.
|
||||||
|
*/
|
||||||
addControl(dir: NgModel): void {
|
addControl(dir: NgModel): void {
|
||||||
resolvedPromise.then(() => {
|
resolvedPromise.then(() => {
|
||||||
const container = this._findContainer(dir.path);
|
const container = this._findContainer(dir.path);
|
||||||
|
@ -138,8 +191,20 @@ export class NgForm extends ControlContainer implements Form,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description
|
||||||
|
* Retrieves the `FormControl` instance from the provided `NgModel` directive.
|
||||||
|
*
|
||||||
|
* @param dir The `NgModel` directive instance.
|
||||||
|
*/
|
||||||
getControl(dir: NgModel): FormControl { return <FormControl>this.form.get(dir.path); }
|
getControl(dir: NgModel): FormControl { return <FormControl>this.form.get(dir.path); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description
|
||||||
|
* Removes the `NgModel` instance from the internal list of directives
|
||||||
|
*
|
||||||
|
* @param dir The `NgModel` directive instance.
|
||||||
|
*/
|
||||||
removeControl(dir: NgModel): void {
|
removeControl(dir: NgModel): void {
|
||||||
resolvedPromise.then(() => {
|
resolvedPromise.then(() => {
|
||||||
const container = this._findContainer(dir.path);
|
const container = this._findContainer(dir.path);
|
||||||
|
@ -150,6 +215,12 @@ export class NgForm extends ControlContainer implements Form,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description
|
||||||
|
* Adds a new `NgModelGroup` directive instance to the form.
|
||||||
|
*
|
||||||
|
* @param dir The `NgModelGroup` directive instance.
|
||||||
|
*/
|
||||||
addFormGroup(dir: NgModelGroup): void {
|
addFormGroup(dir: NgModelGroup): void {
|
||||||
resolvedPromise.then(() => {
|
resolvedPromise.then(() => {
|
||||||
const container = this._findContainer(dir.path);
|
const container = this._findContainer(dir.path);
|
||||||
|
@ -160,6 +231,12 @@ export class NgForm extends ControlContainer implements Form,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description
|
||||||
|
* Removes the `NgModelGroup` directive instance from the form.
|
||||||
|
*
|
||||||
|
* @param dir The `NgModelGroup` directive instance.
|
||||||
|
*/
|
||||||
removeFormGroup(dir: NgModelGroup): void {
|
removeFormGroup(dir: NgModelGroup): void {
|
||||||
resolvedPromise.then(() => {
|
resolvedPromise.then(() => {
|
||||||
const container = this._findContainer(dir.path);
|
const container = this._findContainer(dir.path);
|
||||||
|
@ -169,8 +246,20 @@ export class NgForm extends ControlContainer implements Form,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description
|
||||||
|
* Retrieves the `FormGroup` for a provided `NgModelGroup` directive instance
|
||||||
|
*
|
||||||
|
* @param dir The `NgModelGroup` directive instance.
|
||||||
|
*/
|
||||||
getFormGroup(dir: NgModelGroup): FormGroup { return <FormGroup>this.form.get(dir.path); }
|
getFormGroup(dir: NgModelGroup): FormGroup { return <FormGroup>this.form.get(dir.path); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the new value for the provided `NgControl` directive.
|
||||||
|
*
|
||||||
|
* @param dir The `NgControl` directive instance.
|
||||||
|
* @param value The new value for the directive's control.
|
||||||
|
*/
|
||||||
updateModel(dir: NgControl, value: any): void {
|
updateModel(dir: NgControl, value: any): void {
|
||||||
resolvedPromise.then(() => {
|
resolvedPromise.then(() => {
|
||||||
const ctrl = <FormControl>this.form.get(dir.path !);
|
const ctrl = <FormControl>this.form.get(dir.path !);
|
||||||
|
@ -178,8 +267,21 @@ export class NgForm extends ControlContainer implements Form,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description
|
||||||
|
* Sets the value for this `FormGroup`.
|
||||||
|
*
|
||||||
|
* @param value The new value
|
||||||
|
*/
|
||||||
setValue(value: {[key: string]: any}): void { this.control.setValue(value); }
|
setValue(value: {[key: string]: any}): void { this.control.setValue(value); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description
|
||||||
|
* Method called when 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);
|
||||||
|
@ -187,8 +289,18 @@ export class NgForm 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;
|
||||||
|
|
|
@ -10,7 +10,8 @@ import {Directive, Inject, InjectionToken, Optional} from '@angular/core';
|
||||||
import {TemplateDrivenErrors} from './template_driven_errors';
|
import {TemplateDrivenErrors} from './template_driven_errors';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Token to provide to turn off the warning when using 'ngForm' deprecated selector.
|
* @description
|
||||||
|
* `InjectionToken` to provide to turn off the warning when using 'ngForm' deprecated selector.
|
||||||
*/
|
*/
|
||||||
export const NG_FORM_SELECTOR_WARNING = new InjectionToken('NgFormSelectorWarning');
|
export const NG_FORM_SELECTOR_WARNING = new InjectionToken('NgFormSelectorWarning');
|
||||||
|
|
||||||
|
|
|
@ -47,55 +47,83 @@ const resolvedPromise = Promise.resolve(null);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @description
|
* @description
|
||||||
*
|
|
||||||
* Creates a `FormControl` instance from a domain model and binds it
|
* Creates a `FormControl` instance from a domain model and binds it
|
||||||
* to a form control element.
|
* to a form control element.
|
||||||
*
|
*
|
||||||
* The `FormControl` instance will track the value, user interaction, and
|
* The `FormControl` instance tracks the value, user interaction, and
|
||||||
* validation status of the control and keep the view synced with the model. If used
|
* validation status of the control and keeps the view synced with the model. If used
|
||||||
* within a parent form, the directive will also register itself with the form as a child
|
* within a parent form, the directive also registers itself with the form as a child
|
||||||
* control.
|
* control.
|
||||||
*
|
*
|
||||||
* This directive can be used by itself or as part of a larger form. All you need is the
|
* This directive is used by itself or as part of a larger form. Use the
|
||||||
* `ngModel` selector to activate it.
|
* `ngModel` selector to activate it.
|
||||||
*
|
*
|
||||||
* It accepts a domain model as an optional `Input`. If you have a one-way binding
|
* It accepts a domain model as an optional `Input`. If you have a one-way binding
|
||||||
* to `ngModel` with `[]` syntax, changing the value of the domain model in the component
|
* to `ngModel` with `[]` syntax, changing the value of the domain model in the component
|
||||||
* class will set the value in the view. If you have a two-way binding with `[()]` syntax
|
* class sets the value in the view. If you have a two-way binding with `[()]` syntax
|
||||||
* (also known as 'banana-box syntax'), the value in the UI will always be synced back to
|
* (also known as 'banana-box syntax'), the value in the UI always syncs back to
|
||||||
* the domain model in your class as well.
|
* the domain model in your class.
|
||||||
*
|
*
|
||||||
* If you wish to inspect the properties of the associated `FormControl` (like
|
* To inspect the properties of the associated `FormControl` (like validity state),
|
||||||
* validity state), you can also export the directive into a local template variable using
|
* export the directive into a local template variable using `ngModel` as the key (ex: `#myVar="ngModel"`).
|
||||||
* `ngModel` as the key (ex: `#myVar="ngModel"`). You can then access the control using the
|
* You then access the control using the directive's `control` property,
|
||||||
* directive's `control` property, but most properties you'll need (like `valid` and `dirty`)
|
* but most properties used (like `valid` and `dirty`) fall through to the control anyway for direct access.
|
||||||
* will fall through to the control anyway, so you can access them directly. You can see a
|
* See a full list of properties directly available in `AbstractControlDirective`.
|
||||||
* full list of properties directly available in `AbstractControlDirective`.
|
|
||||||
*
|
*
|
||||||
* The following is an example of a simple standalone control using `ngModel`:
|
* @see `RadioControlValueAccessor`
|
||||||
|
* @see `SelectControlValueAccessor`
|
||||||
|
*
|
||||||
|
* @usageNotes
|
||||||
|
*
|
||||||
|
* ### Using ngModel on a standalone control
|
||||||
|
*
|
||||||
|
* The following examples show a simple standalone control using `ngModel`:
|
||||||
*
|
*
|
||||||
* {@example forms/ts/simpleNgModel/simple_ng_model_example.ts region='Component'}
|
* {@example forms/ts/simpleNgModel/simple_ng_model_example.ts region='Component'}
|
||||||
*
|
*
|
||||||
* When using the `ngModel` within `<form>` tags, you'll also need to supply a `name` attribute
|
* When using the `ngModel` within `<form>` tags, you'll also need to supply a `name` attribute
|
||||||
* so that the control can be registered with the parent form under that name.
|
* so that the control can be registered with the parent form under that name.
|
||||||
*
|
*
|
||||||
* It's worth noting that in the context of a parent form, you often can skip one-way or
|
* In the context of a parent form, it's often unnecessary to include one-way or two-way binding,
|
||||||
* two-way binding because the parent form will sync the value for you. You can access
|
* as the parent form syncs the value for you. You access its properties by exporting it into a
|
||||||
* its properties by exporting it into a local template variable using `ngForm` (ex:
|
* local template variable using `ngForm` such as (`#f="ngForm"`). Use the variable where
|
||||||
* `#f="ngForm"`). Then you can pass it where it needs to go on submit.
|
* needed on form submission.
|
||||||
*
|
*
|
||||||
* If you do need to populate initial values into your form, using a one-way binding for
|
* If you do need to populate initial values into your form, using a one-way binding for
|
||||||
* `ngModel` tends to be sufficient as long as you use the exported form's value rather
|
* `ngModel` tends to be sufficient as long as you use the exported form's value rather
|
||||||
* than the domain model's value on submit.
|
* than the domain model's value on submit.
|
||||||
|
*
|
||||||
|
* ### Using ngModel within a form
|
||||||
*
|
*
|
||||||
* Take a look at an example of using `ngModel` within a form:
|
* The following example shows controls using `ngModel` within a form:
|
||||||
*
|
*
|
||||||
* {@example forms/ts/simpleForm/simple_form_example.ts region='Component'}
|
* {@example forms/ts/simpleForm/simple_form_example.ts region='Component'}
|
||||||
|
*
|
||||||
|
* ### Using a standalone ngModel within a group
|
||||||
|
*
|
||||||
|
* The following example shows you how to use a standalone ngModel control
|
||||||
|
* within a form. This controls the display of the form, but doesn't contain form data.
|
||||||
*
|
*
|
||||||
* To see `ngModel` examples with different form control types, see:
|
* ```html
|
||||||
|
* <form>
|
||||||
|
* <input name="login" ngModel placeholder="Login">
|
||||||
|
* <input type="checkbox" ngModel [ngModelOptions]="{standalone: true}"> Show more options?
|
||||||
|
* </form>
|
||||||
|
* <!-- form value: {login: ''} -->
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* ### Setting the ngModel name attribute through options
|
||||||
|
*
|
||||||
|
* The following example shows you an alternate way to set the name attribute. The name attribute is used
|
||||||
|
* within a custom form component, and the name `@Input` property serves a different purpose.
|
||||||
*
|
*
|
||||||
* * Radio buttons: `RadioControlValueAccessor`
|
* ```html
|
||||||
* * Selects: `SelectControlValueAccessor`
|
* <form>
|
||||||
|
* <my-person-control name="Nancy" ngModel [ngModelOptions]="{name: 'user'}">
|
||||||
|
* </my-person-control>
|
||||||
|
* </form>
|
||||||
|
* <!-- form value: {user: ''} -->
|
||||||
|
* ```
|
||||||
*
|
*
|
||||||
* @ngModule FormsModule
|
* @ngModule FormsModule
|
||||||
* @publicApi
|
* @publicApi
|
||||||
|
@ -110,55 +138,58 @@ export class NgModel extends NgControl implements OnChanges,
|
||||||
public readonly control: FormControl = new FormControl();
|
public readonly control: FormControl = new FormControl();
|
||||||
/** @internal */
|
/** @internal */
|
||||||
_registered = false;
|
_registered = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description
|
||||||
|
* Internal reference to the view model value.
|
||||||
|
*/
|
||||||
viewModel: any;
|
viewModel: any;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description
|
||||||
|
* Tracks the name bound to the directive. The parent form
|
||||||
|
* uses this name as a key to retrieve this control's value.
|
||||||
|
*/
|
||||||
// TODO(issue/24571): remove '!'.
|
// TODO(issue/24571): remove '!'.
|
||||||
@Input() name !: string;
|
@Input() name !: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description
|
||||||
|
* Tracks whether the control is disabled.
|
||||||
|
*/
|
||||||
// TODO(issue/24571): remove '!'.
|
// TODO(issue/24571): remove '!'.
|
||||||
@Input('disabled') isDisabled !: boolean;
|
@Input('disabled') isDisabled !: boolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description
|
||||||
|
* Tracks the value bound to this directive.
|
||||||
|
*/
|
||||||
@Input('ngModel') model: any;
|
@Input('ngModel') model: any;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Options object for this `ngModel` instance. You can configure the following properties:
|
* @description
|
||||||
|
* Tracks the configuration options for this `ngModel` instance.
|
||||||
*
|
*
|
||||||
* **name**: An alternative to setting the name attribute on the form control element.
|
* **name**: An alternative to setting the name attribute on the form control element. See
|
||||||
* Sometimes, especially with custom form components, the name attribute might be used
|
* the [example](api/forms/NgModel#using-ngmodel-on-a-standalone-control) for using `NgModel`
|
||||||
* as an `@Input` property for a different purpose. In cases like these, you can configure
|
* as a standalone control.
|
||||||
* the `ngModel` name through this option.
|
|
||||||
*
|
*
|
||||||
* ```html
|
* **standalone**: When set to true, the `ngModel` will not register itself with its parent form,
|
||||||
* <form>
|
* and acts as if it's not in the form. Defaults to false.
|
||||||
* <my-person-control name="Nancy" ngModel [ngModelOptions]="{name: 'user'}">
|
|
||||||
* </my-person-control>
|
|
||||||
* </form>
|
|
||||||
* <!-- form value: {user: ''} -->
|
|
||||||
* ```
|
|
||||||
*
|
*
|
||||||
* **standalone**: Defaults to false. If this is set to true, the `ngModel` will not
|
* **updateOn**: Defines the event upon which the form control value and validity update.
|
||||||
* register itself with its parent form, and will act as if it's not in the form. This
|
* Defaults to 'change'. Possible values: `'change'` | `'blur'` | `'submit'`.
|
||||||
* can be handy if you have form meta-controls, a.k.a. form elements nested in
|
|
||||||
* the `<form>` tag that control the display of the form, but don't contain form data.
|
|
||||||
*
|
|
||||||
* ```html
|
|
||||||
* <form>
|
|
||||||
* <input name="login" ngModel placeholder="Login">
|
|
||||||
* <input type="checkbox" ngModel [ngModelOptions]="{standalone: true}"> Show more options?
|
|
||||||
* </form>
|
|
||||||
* <!-- form value: {login: ''} -->
|
|
||||||
* ```
|
|
||||||
*
|
|
||||||
* **updateOn**: Defaults to `'change'`. Defines the event upon which the form control
|
|
||||||
* value and validity will update. Also accepts `'blur'` and `'submit'`.
|
|
||||||
*
|
|
||||||
* ```html
|
|
||||||
* <input [(ngModel)]="firstName" [ngModelOptions]="{updateOn: 'blur'}">
|
|
||||||
* ```
|
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
// TODO(issue/24571): remove '!'.
|
// TODO(issue/24571): remove '!'.
|
||||||
@Input('ngModelOptions')
|
@Input('ngModelOptions')
|
||||||
options !: {name?: string, standalone?: boolean, updateOn?: FormHooks};
|
options !: {name?: string, standalone?: boolean, updateOn?: FormHooks};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description
|
||||||
|
* Event emitter for producing the `ngModelChange` event after
|
||||||
|
* the view model updates.
|
||||||
|
*/
|
||||||
@Output('ngModelChange') update = new EventEmitter();
|
@Output('ngModelChange') update = new EventEmitter();
|
||||||
|
|
||||||
constructor(@Optional() @Host() parent: ControlContainer,
|
constructor(@Optional() @Host() parent: ControlContainer,
|
||||||
|
@ -173,6 +204,13 @@ export class NgModel 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) {
|
ngOnChanges(changes: SimpleChanges) {
|
||||||
this._checkForErrors();
|
this._checkForErrors();
|
||||||
if (!this._registered) this._setUpControl();
|
if (!this._registered) this._setUpControl();
|
||||||
|
@ -186,20 +224,50 @@ export class NgModel extends NgControl implements OnChanges,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description
|
||||||
|
* Lifecycle method called before the directive's instance is destroyed. For internal
|
||||||
|
* use only.
|
||||||
|
*/
|
||||||
ngOnDestroy(): void { this.formDirective && this.formDirective.removeControl(this); }
|
ngOnDestroy(): void { this.formDirective && this.formDirective.removeControl(this); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @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[] {
|
get path(): string[] {
|
||||||
return this._parent ? controlPath(this.name, this._parent) : [this.name];
|
return this._parent ? controlPath(this.name, this._parent) : [this.name];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description
|
||||||
|
* The top-level directive for this control 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|null {
|
get asyncValidator(): AsyncValidatorFn|null {
|
||||||
return composeAsyncValidators(this._rawAsyncValidators);
|
return composeAsyncValidators(this._rawAsyncValidators);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description
|
||||||
|
* Sets the new value for the view model and emits an `ngModelChange` event.
|
||||||
|
*
|
||||||
|
* @param newValue The new value emitted by `ngModelChange`.
|
||||||
|
*/
|
||||||
viewToModelUpdate(newValue: any): void {
|
viewToModelUpdate(newValue: any): void {
|
||||||
this.viewModel = newValue;
|
this.viewModel = newValue;
|
||||||
this.update.emit(newValue);
|
this.update.emit(newValue);
|
||||||
|
|
|
@ -22,21 +22,25 @@ export const modelGroupProvider: any = {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @description
|
* @description
|
||||||
*
|
|
||||||
* Creates and binds a `FormGroup` instance to a DOM element.
|
* Creates and binds a `FormGroup` instance to a DOM element.
|
||||||
*
|
*
|
||||||
* This directive can only be used as a child of `NgForm` (or in other words,
|
* This directive can only be used as a child of `NgForm` (within `<form>` tags).
|
||||||
* within `<form>` tags).
|
|
||||||
*
|
*
|
||||||
* Use this directive if you'd like to create a sub-group within a form. This can
|
* Use this directive to validate a sub-group of your form separately from the
|
||||||
* come in handy if you want to validate a sub-group of your form separately from
|
* rest of your form, or if some values in your domain model make more sense
|
||||||
* the rest of your form, or if some values in your domain model make more sense to
|
* to consume together in a nested object.
|
||||||
* consume together in a nested object.
|
|
||||||
*
|
*
|
||||||
* Pass in the name you'd like this sub-group to have and it will become the key
|
* Provide a name for the sub-group and it will become the key
|
||||||
* for the sub-group in the form's full value. You can also export the directive into
|
* for the sub-group in the form's full value. If you need direct access, export the directive into
|
||||||
* a local template variable using `ngModelGroup` (ex: `#myGroup="ngModelGroup"`).
|
* a local template variable using `ngModelGroup` (ex: `#myGroup="ngModelGroup"`).
|
||||||
*
|
*
|
||||||
|
* @usageNotes
|
||||||
|
*
|
||||||
|
* ### Consuming controls in a grouping
|
||||||
|
*
|
||||||
|
* The following example shows you how to combine controls together in a sub-group
|
||||||
|
* of the form.
|
||||||
|
*
|
||||||
* {@example forms/ts/ngModelGroup/ng_model_group_example.ts region='Component'}
|
* {@example forms/ts/ngModelGroup/ng_model_group_example.ts region='Component'}
|
||||||
*
|
*
|
||||||
* @ngModule FormsModule
|
* @ngModule FormsModule
|
||||||
|
@ -44,6 +48,11 @@ export const modelGroupProvider: any = {
|
||||||
*/
|
*/
|
||||||
@Directive({selector: '[ngModelGroup]', providers: [modelGroupProvider], exportAs: 'ngModelGroup'})
|
@Directive({selector: '[ngModelGroup]', providers: [modelGroupProvider], exportAs: 'ngModelGroup'})
|
||||||
export class NgModelGroup extends AbstractFormGroupDirective implements OnInit, OnDestroy {
|
export class NgModelGroup extends AbstractFormGroupDirective implements OnInit, OnDestroy {
|
||||||
|
/**
|
||||||
|
* @description
|
||||||
|
* Tracks the name of the `NgModelGroup` bound to the directive. The name corresponds
|
||||||
|
* to a key in the parent `NgForm`.
|
||||||
|
*/
|
||||||
// TODO(issue/24571): remove '!'.
|
// TODO(issue/24571): remove '!'.
|
||||||
@Input('ngModelGroup') name !: string;
|
@Input('ngModelGroup') name !: string;
|
||||||
|
|
||||||
|
|
|
@ -215,8 +215,6 @@ export class FormControlName extends NgControl implements OnChanges, OnDestroy {
|
||||||
/**
|
/**
|
||||||
* @description
|
* @description
|
||||||
* Lifecycle method called before the directive's instance is destroyed. For internal use only.
|
* 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) {
|
||||||
|
|
Loading…
Reference in New Issue