Form stuck in PENDING status with async validator when value changed on construction
Asked Answered
B

2

6

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?

Broadleaved answered 12/11, 2019 at 11:21 Comment(3)
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://mcmap.net/q/1916210/-error-alerts-in-angular-reactive-forms-appear-one-step-lateVaricelloid
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...Broadleaved
in if case i was sending values but I was missing below code in else case. observer.next(null); observer.complete(); return { unsubscribe() { null } };Zackzackariah
A
2

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.

Alarcon answered 26/5, 2020 at 9:53 Comment(0)
R
0

Had the same issue solved it by using a debounceTime like so:

this.form.valueChanges.pipe(debounceTime(400), distinctUntilChanged()).subscribe(val => {
if (!this.form.pristine) {
    if (val.Name && this.form.valid) {
        this.portalInfo['Name'] = val.Name;
    }
}});
Radiocarbon answered 13/3 at 21:30 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.