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.

2
  • You have added emailAsyncValidatorDirective to your template, but the implementation code is missing. Can you please provide that as well in your initial question. Commented Jul 31, 2021 at 8:27
  • I first tried to do it with directive, but failed too :D, now i will remove it, thanks for pointing it out. Commented Jul 31, 2021 at 8:29

1 Answer 1

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?.

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

1 Comment

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.

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.