Code Explorer
Code Explorer

Reputation: 65

Async custom validator not working and showing error message in Angular 8

I am new to Angular 8 and trying to create custom async validator. Below is my code:

In my typescript file I am creating form field like below. I am using only async validator(no sync validator so passing 'null' as second parameter):

group.addControl(control.Name, this.fb.control('', null, this.phoneValidator));

Below is my async validator code:

phoneValidator(control: AbstractControl) {
    if(control.value == '' || control.value == undefined || control.value == null) {
      return null;
    }
    else {
      return this.phoneValidatorServiceCall(control.value)
        //.pipe(map((data: any) => {
        //  return (data.Response == "True" ? null : { phoneValidator: true });
        //}))
        .subscribe(data => {
            return (data.Response == "True" ? null : { phoneValidator: true });
        })
      }
   }

In above code I tried to use "Pipe" only it's not working so used "Subscribe" only but even this not working. Below is my service method:

phoneValidatorServiceCall(input): Observable<any> {
   return this.http.post<any>('http://xxxxxxxx:xxxx/validate/phone', { 'Text': input });
}

For showing error in html I am using below code:

<mat-form-field class="example-full-width">
<input #dyInput [formControlName]="Phone" matInput [placeholder]="Phone" [required]="IsRequiredField">

<!-- For showing validation message(s) (Start) -->
<mat-error *ngFor="let v of Config.Validators">
  {{ f.controls['Phone'].invalid }} // comes true only on error
  {{ f.controls['Phone'].hasError("phoneValidator") }} // always coming false even for wrong input
  <strong *ngIf="f.controls['Phone'].invalid && f.controls['Phone'].hasError('phoneValidator')">
    {{ My Message Here }}
  </strong>
</mat-error>
<!-- For showing validation message(s) (End) -->

I am facing two problems:

  1. It's not waiting for response from service. Somehow it's always return error from phoneValidator(control: AbstractControl) method
  2. Error message not showing on screen. f.controls['Phone'].hasError("phoneValidator") always coming false

Upvotes: 3

Views: 10385

Answers (2)

AVJT82
AVJT82

Reputation: 73357

You have been given good tips on how to solve your problem. Those gathered... So your current issues are:

Add return type of validator:

Observable<ValidationErrors | null>

Since that is what you are going to return.

So don't subscribe in the validator, instead return the observable. Also, you need to return of(null) when valid, since again... we need to return an observable. So modify your validator to:

import { of } from 'rxjs';

//....

phoneValidator(control: AbstractControl): Observable<ValidationErrors | null> {
  if (!control.value) {
    return of(null);
  } else {
    return this.phoneValidatorServiceCall(control.value)
      .pipe(map((data: any) => {
        return (data.Response == "True" ? null : { phoneValidator: true });
      }))
  }
}

Upvotes: 4

Akash
Akash

Reputation: 4602

There are couple of problems -

  1. The return type of phoneValidator should be Promise<ValidationErrors | null> | Observable<ValidationErrors | null>.
  2. Do something like below so that you return an observable and check if your second problem gets solved -

return observableOf({ phoneValidator: true });

  1. Use pipe and map your response.

Upvotes: 0

Related Questions