Angular Reactive Forms - async validator is not working

Viewed 20

I have created 2 almost identical async validators.

uniqueTitleValidator - This validates for existing string with a simple array 'titles'

titleExist(title: string): Observable<boolean> {
    return of(title).pipe(
      map((title) => {
        const titles = ['abc', '123'];
        return titles.includes(title);
      })
    );
  }

  uniqueTitleValidator(): AsyncValidatorFn {
    return (control: AbstractControl): Observable<ValidationErrors | null> => {
      return this.titleExist(control.value).pipe(
        map((exists) => {
          console.log('exists title', exists);
          return exists ? { titleExist: true } : null;
        })
      );
    };
  }

uniqueVoucherValidator - This validates for an existing string by retrieving data from FireStore

voucherExist(title: string, paymentService: PaymentService): Observable<any> {
    return paymentService.getAllPayment().pipe(
      map((payments) => {
        console.log('payments', payments);
        const payment = payments.find(
          (item: any) =>
            item.data.voucherTitle.toLowerCase() == title.toLowerCase()
        );
        console.log('payment validator', payment);
        return !!payment;
      })
    );
  }

  uniqueVoucherValidator(paymentService: PaymentService): AsyncValidatorFn {
    return (control: AbstractControl): Observable<ValidationErrors | null> => {
      return this.voucherExist(control.value, paymentService).pipe(
        map((exists) => {
          console.log('exists voucher', exists);
          return exists ? { voucherExist: true } : null;
        })
      );
    };
  }

Both works and from the screen shot console - you can see the boolean for 'exists title' and 'exist voucher' are returned correctly. However, only the second validator - uniqueVoucherValidator - the validation error is always reflected as null.

form.control.voucherTitle.errors is reflecting the correct validation result

form.control.voucherTitle.errors is always null

Need some advice on what could have caused the uniqueVoucherValidator to always show null.

1 Answers

Since Firebase api has not completed.The form control is still in pending status you can use take(1) operator to complete observable manually

voucherExist(title: string, paymentService: PaymentService): Observable<any> {
    return paymentService.getAllPayment().pipe(
      map((payments) => {
        console.log('payments', payments);
        const payment = payments.find(
          (item: any) =>
            item.data.voucherTitle.toLowerCase() == title.toLowerCase()
        );
        console.log('payment validator', payment);
        return !!payment;
      }),
      take(1)
    );
  }
Related