4

When using reactive forms with an async validator on the form group, and if changing the values of the form group by using patchValue in the constructor or in ngOnInit - even though the async validator observable completes, the form remains in PENDING state.

I've created a SSCCE in Stackblitz

In the example, you see a simple form with two fields, with an indication of the form status, and the validator state. In the code, in ngOnInit I call patchValue on the form, causing the form to go into PENDING status, and the async validator to be called.

The async validator doesn't do much, it simply waits for 1 second then returns a null errors object basically saying that the form is valid. You can see in the indications that the validation completed, but the form stays in PENDING status.

If you trigger a change in field values at any time other than in the constructor or in ngOnInit (i.e. on object construction) - then the form does go into VALID status when the validator completes. This also applies if you wrap the value change in setTimeout.

Am I doing something wrong? Is this normal behavior, or is this a bug in Angular?

Aviad P.
  • 32,036
  • 14
  • 103
  • 124
  • 1
    I can't pinpoint exactly what is going on and which values are stuck in pending state, but I can say that it definitely has to do with the fact that angular forms are asynchronous, so when you call `patchValue` "too fast" (before the form has been completely built and prev values set), it causes this. So no, not a bug, it is caused by angular forms being asynchronous. There are sometimes other issues caused by forms being asynchrnous, so you sometimes need to wait a tick (using settimeout) before doing something, here's one (unrelated) question https://stackoverflow.com/a/58578113/6294072 – AT82 Nov 13 '19 at 08:10
  • Thanks @AJT82 I would say it's either a feature (possibly undocumented) or a bug. If it's a feature it should be described in a specification, if it's a bug it should be opened as an issue. But anyway, I would put in a warning either in runtime or during compile that `patchValue` shouldn't be called in the same frame that creates the `FormGroup`... – Aviad P. Nov 13 '19 at 08:44
  • in if case i was sending values but I was missing below code in else case. observer.next(null); observer.complete(); return { unsubscribe() { null } }; – garish May 17 '22 at 10:32

1 Answers1

1

I had a similar issue, after async validator, form stuck on PENDING and this is how I deal with it:
1) make observable of status change:

this.form$ = this.form.statusChanges;

2) subscribe to observable:

this.form$.subscribe( r => {
  if (r === 'VALID') {
    //form valid
  } else if( r === 'PENDING') {
    setTimeout(() => {
      this.form.updateValueAndValidity(); // this function will trigger statusChange one more time.
    }, 2000);
  } else {
    // any other status
  }
});

So if async validator finished but didn't trigger statusChange then all You can do is trigger statusChange one more time by Yourself.

DanielWaw
  • 669
  • 7
  • 22