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:
Kara Erickson
2017-08-07 21:11:46 -07:00
committed by Hans
parent cce2ab2625
commit 1cfa79ca4e
7 changed files with 578 additions and 24 deletions

View File

@ -819,6 +819,22 @@ export function main() {
expect(control.dirty).toBe(true, 'Expected control to update dirty state when blurred.');
});
it('should update touched when control is blurred', () => {
const fixture = initTest(FormControlComp);
const control = new FormControl('', {updateOn: 'blur'});
fixture.componentInstance.control = control;
fixture.detectChanges();
expect(control.touched).toBe(false, 'Expected control to start out untouched.');
const input = fixture.debugElement.query(By.css('input')).nativeElement;
dispatchEvent(input, 'blur');
fixture.detectChanges();
expect(control.touched)
.toBe(true, 'Expected control to update touched state when blurred.');
});
it('should continue waiting for blur to update if previously blurred', () => {
const fixture = initTest(FormControlComp);
const control =