Skip to content

Commit

Permalink
fix(forms): changes to status not always being emitted to statusChang…
Browse files Browse the repository at this point in the history
…es 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.
  • Loading branch information
dylhunn committed Jun 10, 2021
1 parent efb440e commit b005cd3
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 3 deletions.
6 changes: 3 additions & 3 deletions packages/forms/src/model.ts
Expand Up @@ -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
});
}

Expand Down Expand Up @@ -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
});
}

Expand Down Expand Up @@ -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
});
}

Expand Down
20 changes: 20 additions & 0 deletions packages/forms/test/form_control_spec.ts
Expand Up @@ -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() {
Expand Down Expand Up @@ -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'));

Expand Down

0 comments on commit b005cd3

Please sign in to comment.