feat(forms): add updateOn support to ngModelOptions
This commit introduces a new option to template-driven forms that improves performance by delaying form control updates until the "blur" or "submit" event. To use it, set the `updateOn` property in `ngModelOptions`. ```html <input ngModel [ngModelOptions]="{updateOn: blur}"> ``` Like in AngularJS, setting `updateOn` to `blur` or `submit` will delay the update of the value as well as the validation status. Updating value and validity together keeps the system easy to reason about, as the two will always be in sync. It's also worth noting that the value/validation pipeline does still run when the form is initialized (in order to support initial values). Upcoming PRs will address: * Support for setting group-level `updateOn` in template-driven forms * Option for skipping initial validation run or more global error display configuration * Better support of reactive validation strategies See more context in #18408, #18514, and the [design doc](https://docs.google.com/document/d/1dlJjRXYeuHRygryK0XoFrZNqW86jH4wobftCFyYa1PA/edit#heading=h.r6gn0i8f19wz).
This commit is contained in:
@ -8,7 +8,7 @@
|
||||
|
||||
import {Directive, EventEmitter, Host, Inject, Input, OnChanges, OnDestroy, Optional, Output, Self, SimpleChanges, forwardRef} from '@angular/core';
|
||||
|
||||
import {FormControl} from '../model';
|
||||
import {FormControl, FormHooks} from '../model';
|
||||
import {NG_ASYNC_VALIDATORS, NG_VALIDATORS} from '../validators';
|
||||
|
||||
import {AbstractFormGroupDirective} from './abstract_form_group_directive';
|
||||
@ -119,7 +119,45 @@ export class NgModel extends NgControl implements OnChanges,
|
||||
@Input() name: string;
|
||||
@Input('disabled') isDisabled: boolean;
|
||||
@Input('ngModel') model: any;
|
||||
@Input('ngModelOptions') options: {name?: string, standalone?: boolean};
|
||||
|
||||
/**
|
||||
* Options object for this `ngModel` instance. You can configure the following properties:
|
||||
*
|
||||
* **name**: An alternative to setting the name attribute on the form control element.
|
||||
* Sometimes, especially with custom form components, the name attribute might be used
|
||||
* as an `@Input` property for a different purpose. In cases like these, you can configure
|
||||
* the `ngModel` name through this option.
|
||||
*
|
||||
* ```html
|
||||
* <form>
|
||||
* <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
|
||||
* register itself with its parent form, and will act as if it's not in the form. This
|
||||
* 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'}">
|
||||
* ```
|
||||
*
|
||||
*/
|
||||
@Input('ngModelOptions') options: {name?: string, standalone?: boolean, updateOn?: FormHooks};
|
||||
|
||||
@Output('ngModelChange') update = new EventEmitter();
|
||||
|
||||
@ -170,11 +208,18 @@ export class NgModel extends NgControl implements OnChanges,
|
||||
}
|
||||
|
||||
private _setUpControl(): void {
|
||||
this._setUpdateStrategy();
|
||||
this._isStandalone() ? this._setUpStandalone() :
|
||||
this.formDirective.addControl(this);
|
||||
this._registered = true;
|
||||
}
|
||||
|
||||
private _setUpdateStrategy(): void {
|
||||
if (this.options && this.options.updateOn != null) {
|
||||
this._control._updateOn = this.options.updateOn;
|
||||
}
|
||||
}
|
||||
|
||||
private _isStandalone(): boolean {
|
||||
return !this._parent || !!(this.options && this.options.standalone);
|
||||
}
|
||||
|
Reference in New Issue
Block a user