Search code examples
angularangular-reactive-forms

Using Observable inside Custom Validator Angular


so I am creating a validator which checks if the username is already taken.

I have the following Custom validator definition:

import { AbstractControl } from '@angular/forms';
import { AccountApi } from '../../api/service/account.api';
import { Injectable } from '@angular/core';
import { switchMap, mapTo, catchError } from 'rxjs/operators';
import { of, timer } from 'rxjs';


@Injectable()
export class UsernameValidator {
  constructor(private api: AccountApi) {

  }

  exists(control: AbstractControl) {
    // this.api.checkUsernameIfExisting(control.value).subscribe((existing) => {
    //   control.setErrors({ exists: existing });
    // });

    // return null;

    return timer(100).pipe(
      switchMap(() => this.api.checkUsernameIfExisting(control.value).pipe(
          // Successful response, set validator to null
          mapTo(null),
          // Set error object on error response
          catchError(() => of({ exists: true }))
        )
      )
    );
  }
}

This is how I used it:

 username: ['', [
    Validators.required,
    Validators.minLength(6),
    Validators.maxLength(30),
    this.usernameValidator.exists.bind(this.usernameValidator)
 ]],

My question is, why does the call on my API doesn't get triggered? I checked if the form is calling exists() and it calls it.

Thanks!


Solution

  • Async validators should go after sync validators.

    So I would try something like this:

    username: ['', [
      Validators.required,
      Validators.minLength(6),
      Validators.maxLength(30),
     ],
     this.usernameValidator.exists.bind(this.usernameValidator)
    ],