1

This is my first time trying an async form validator. It is attached at to my form's asyncValidators, it's firing appropriately, the correct value (object or null) is being returned ... but the form remains invalid and the state stuck in PENDING. The errors property on all formgroups and formcontrols is null.

If I remove the async validator, the issue goes away, so it is 100% the validator.

This is an old component that someone injected ChangeDetectorRef into, but is not an onPush component. I have tried using the cd to mark for check and explicitly detectChanges().

Can someone tell me what I'm doing wrong?

Validator:

private validateV2Applications$(): AsyncValidatorFn {
    return (): Observable<ValidationErrors> => {
      console.log("called");
      return this.applyChargesService.rowInfo$.pipe(
        map((rowInfo) => {
          console.log('mapped');
          if (this.useApplyToInstallments && rowInfo.invalidRows.length > 0) {
            console.log('async validator is invalid!');
            return { applicationErrors: 'there are application errors' };
          }

          return null;
        }),
      );
    };
  }

Form creation code (wasn't sure how to add as part of formBuilder so adding after-the-fact):

// fb = FormBuilder
this.creditForm = this.fb.group(
  { /* form controls */ },
  {
    validator: [this.validatecredit(), this.validateApplicationTotal()],
  },
);

this.creditForm.setAsyncValidators([this.validateV2Applications$()]);

EDIT for @naren murali, the code for rowInfo$. The rowInfo$ observable works perfectly fine for every other use case. This code is located in a service, and another component pushes rowInfo to listeners. That "other component" is loaded and pushing values, which I can verify with the log statements.

private rowInfoSource = new BehaviorSubject<ApplyChargesRowInfo>({
  selectedRows: [],
  invalidRows: [],
});
public rowInfo$ = this.rowInfoSource.asObservable();

public setRowInfo(data: ApplyChargesRowInfo): void {
  this.rowInfoSource.next(data);
}
1
  • please share the code of this.applyChargesService.rowInfo$ Commented Dec 18, 2024 at 21:05

1 Answer 1

0

After analyzing your shared code, I don't see any tells that can explain your issue. I suspect a timing issue because you added your async validators after creating the form group. I can help you with one part of your question, and we might get lucky and this solves the problem.

You can register async validators with form builder like so:

// fb = FormBuilder
this.creditForm = this.fb.group(
  { /* form controls */ 
    myControl: [
      '', 
      undefined, /* no validators, or your existing validators here */ 
      [this.validateV2Applications$] /* async validators */
    ] 
  },
  {
    validator: [this.validatecredit(), this.validateApplicationTotal()],
  },
);

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks for the reply. This isn't for a control, though, it's for the form in general, and it's not really tied to the form at all (the validator is validating stuff that isn't on the form, but that needs to be valid for the form to be saved). I think I'll either just add a non-form async validation method that can leave its error message on the form's error panel and tie it to the submit's disable property, or just subscribe to the async rowInfo so I can check it synchronously. Thanks again!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.