1

i`m having problem trying to implement async validator. This is my try:

export class EmailValidator {
    static createValidator(): AsyncValidatorFn {
        return (control: AbstractControl): Observable<ValidationErrors | null> => {
            return of({}).pipe(
                delay(1000),
                tap(() => {
                    const isMatch = /[A-Za-z0-9]{6,}@gmail.com/.test(control.value);
                    return isMatch ? null : { invalidEmail: true }
                })
            )
        };
    }
}

This is basic creation of the form:

this.loginForm = this.fb.group({
      email: [
        '',
        [
          Validators.required,
        ],
        EmailValidator.createValidator()
      ],
      password: [
        '',
        [
          Validators.required,
          Validators.minLength(8)
        ]
      ]
    });

And this is my html:

<div class="container">
    <ul>
        <li class="active"><a routerLink="/login">Login</a></li>
        <li><a routerLink="/auth/register">Register</a></li>
    </ul>
    <form [formGroup]="loginForm" (ngSubmit)="onSubmit()">
        <input formControlName="email" type="email" placeholder="email">
        <div *ngIf="(loginForm.get('email')?.touched || loginForm.get('email')?.dirty) && loginForm.get('email')?.errors?.required">
            Email is required!
        </div>
        <div *ngIf="loginForm.get('email')?.errors?.invalidEmail">
            Email is invalid!
        </div>
        <input formControlName="password" type="password" placeholder="password">
        <input type="submit" value="Login">
    </form>
</div>

When i try to debug inside validator it returns null if match and error object if no match. For some reason error div is not rendering.

LoshoToshi
  • 15
  • 4
  • You have added `emailAsyncValidatorDirective` to your template, but the implementation code is missing. Can you please provide that as well in your initial question. – Santhosh John Jul 31 '21 at 08:27
  • I first tried to do it with directive, but failed too :D, now i will remove it, thanks for pointing it out. – LoshoToshi Jul 31 '21 at 08:29

1 Answers1

2

You should use map instead of tap for rxjs operator.

import { ..., map } from 'rxjs/operators';

export class EmailValidator {
  static createValidator(): AsyncValidatorFn {
    return (control: AbstractControl): Observable<ValidationErrors | null> => {
      return of({}).pipe(
        delay(1000),
        map(() => {
          const isMatch = /[A-Za-z0-9]{6,}@gmail.com/.test(control.value);
          return isMatch ? null : { invalidEmail: true };
        })
      );
    };
  }
}

Sample solution on StackBlitz


You may read What is the difference between tap and map in RxJS?.

Yong Shun
  • 35,286
  • 4
  • 24
  • 46
  • You are welcome. Meanwhile, I updated my answer about the difference between `map` and `tap` in RxJS. You may take your time to read it. Great to see that my answer helps you. Thank you. – Yong Shun Jul 31 '21 at 08:51