From b005cd36167232c9b7d6242d2139a8e87766fa5a Mon Sep 17 00:00:00 2001 From: Dylan Hunn Date: Thu, 10 Jun 2021 14:41:29 -0700 Subject: [PATCH] fix(forms): changes to status not always being emitted to statusChanges observable for async validators. When a FormControl, FormArray, or FormGroup is first constructed, if an async validator is attached, the `statusChanges` observable should receive a message when the validator complete (i.e. pending -> valid/invalid). If the validator was provided as part of the constructor options, it was not fired at construction time, which is fixed in this PR. Fixes #35309. --- packages/forms/src/model.ts | 6 +++--- packages/forms/test/form_control_spec.ts | 20 ++++++++++++++++++++ 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/packages/forms/src/model.ts b/packages/forms/src/model.ts index ae6550a82b578..96c8f320fd89c 100644 --- a/packages/forms/src/model.ts +++ b/packages/forms/src/model.ts @@ -1167,7 +1167,7 @@ export class FormControl extends AbstractControl { // `VALID` or `INVALID`. // The status should be broadcasted via the `statusChanges` observable, so we set `emitEvent` // to `true` to allow that during the control creation process. - emitEvent: !!asyncValidator + emitEvent: !!this.asyncValidator }); } @@ -1433,7 +1433,7 @@ export class FormGroup extends AbstractControl { // If `asyncValidator` is present, it will trigger control status change from `PENDING` to // `VALID` or `INVALID`. The status should be broadcasted via the `statusChanges` observable, // so we set `emitEvent` to `true` to allow that during the control creation process. - emitEvent: !!asyncValidator + emitEvent: !!this.asyncValidator }); } @@ -1887,7 +1887,7 @@ export class FormArray extends AbstractControl { // `VALID` or `INVALID`. // The status should be broadcasted via the `statusChanges` observable, so we set `emitEvent` // to `true` to allow that during the control creation process. - emitEvent: !!asyncValidator + emitEvent: !!this.asyncValidator }); } diff --git a/packages/forms/test/form_control_spec.ts b/packages/forms/test/form_control_spec.ts index d4344e8ce5f1c..5daddd20f4e63 100644 --- a/packages/forms/test/form_control_spec.ts +++ b/packages/forms/test/form_control_spec.ts @@ -10,6 +10,7 @@ import {fakeAsync, tick} from '@angular/core/testing'; import {FormControl, FormGroup, Validators} from '@angular/forms'; import {FormArray} from '@angular/forms/src/model'; +import {expect} from '@angular/platform-browser/testing/src/matchers'; import {asyncValidator, asyncValidatorReturningObservable} from './util'; (function() { @@ -879,6 +880,25 @@ describe('FormControl', () => { tick(); })); + it('should fire statusChanges events for async validators transitioning from pending to valid', + fakeAsync(() => { + let statuses: string[] = []; + + // Create a form control with an async validator. + const asc = new FormControl('', {asyncValidators: [control => Promise.resolve(null)]}); + + // Subscribe to status changes. + asc.statusChanges.subscribe({ + next: (status: any) => { + statuses.push(status); + } + }); + + // After a tick, the async validator should change status PENDING -> VALID. + tick(); + expect(statuses).toEqual(['VALID']); + })); + it('should fire an event after the status has been updated to pending', fakeAsync(() => { const c = new FormControl('old', Validators.required, asyncValidator('expected'));