Search code examples
angulartypescriptpromisecustomvalidator

Angular Custom Validators. How to validate a form field using a given Promise?


I need to validate a form field using a method which returns a Promise. But it never returns the error because Promises are asynchronous.

This is my validator:

static email(usersService: UsersService): ValidatorFn {

  return (control: AbstractControl):{ [key: string]: boolean | null } => {
    const email = control.value;
    if (email) {
      usersService.validateUsername(email).then(
        (result) => { return result.username ? {emailExists: true} : null }
      )
    } else {
      return null;
    }
  }}

This is my UsersService method

validateUsername(username: string): Promise<{"username": string}> {
  return this.httpClient.post('/users/username_validation', {"username": username}).pipe(
    map((body: {"username": string}) => body),
  ).toPromise()}

Solution

  • All I needed to do is use AsyncValidator like this:

    validator.ts

    import { Injectable } from '@angular/core';
    import { AbstractControl, AsyncValidator, ValidationErrors } from '@angular/forms';
    import { Observable} from 'rxjs';
    
    import { UsersService } from "@app/users/users.service";
    
    
    @Injectable({
      providedIn: 'root'
    })
    
    export class EmailValidator implements AsyncValidator {
    
      constructor( private usersService: UsersService ) { }
    
      validate( control: AbstractControl): Promise<ValidationErrors> | Observable<ValidationErrors> {
    
        const email = control.value;
        if (email) {
          return this.usersService.validateUsername(email).then(
            (result) => { 
              console.log(result)
              return result.username ? {emailExists: true} : null 
            }
          )
        } else {
          return null;
        }
    
      }
    }