Async Validation In Angular

Introduction

In this article, I will explain how to implement Async Validation In Angular. Angular does not provide built-in type async Validation implmentation, it provides only for sync validation. The implementation of async validator is very similar to the sync validator. The only difference is that the async Validators must return the result of the validation as an observable or as PromiseIn this article, we will create an async validator for the Existing user. We will check the user exists or not using async validator.

Async Validation In Angular

Prerequisites

  • Angular 12
  • HTML/Bootstrap

For this article, I have created an Angular project using Angular 12. For creating an Angular project, we need to follow the following steps:

Create Project

I have created a project using the following command in the Command Prompt.

ng new AsyncValidatorExample

Open a project in Visual Studio Code using the following commands.

cd AsyncValidatorExample
Code .

Now in Visual Studio, your project looks like as below.

Rules for Async Validator

For creating an Async Validator there are following rules which need to be followed:

  1. The function must implement the AsyncValidatorFn Interface, which defines the signature of the validator function.
  2. The function should be returned in following observable or promise.
  3. If input is valid then must return null, or ValidationErrors if the input is invalid.

AsyncValidatorFn

AsyncValidatorFn is a predefine interface which defines the type of the validator function.

Signature of AsyncValidatorFn

interface AsyncValidatorFn {
  (control: AbstractControl): Promise<ValidationErrors | null> | Observable<ValidationErrors | null>
}

Let's create User Service that will check input user exists or not. For now, we will check it with local parameter not will API call. 

import { Injectable } from '@angular/core';
import { of } from 'rxjs';
import { delay } from 'rxjs/operators';

@Injectable({
  providedIn: 'root',
})
export class UserService {
  private usernames = ['Gajendra', 'Rohit', 'Rohan', 'Ajay'];

  checkIfUsernameExists(value: string) {
    return of(this.usernames.some((a) => a.toLocaleUpperCase() === value.toLocaleUpperCase())).pipe(
      delay(1000)
    );
  }
}

Let's create Async Validator to check if the username exists against that method.

import {
  AbstractControl,
  AsyncValidatorFn,
  ValidationErrors,
} from '@angular/forms';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';
import { UserService } from './user.service';

export class UsernameValidator {
  static createValidator(userService: UserService): AsyncValidatorFn {
    return (control: AbstractControl): Observable<ValidationErrors> => {
      return userService
        .checkIfUsernameExists(control.value)
        .pipe(
          map((result: boolean) =>
            result ? { usernameAlreadyExists: true } : null
          )
        );
    };
  }
}

Use Of Async Validator

this.fb.group({ 
    username: [
      null,
      [UsernameValidator.createValidator(this.userService)],
      updateOn: 'blur'
    ],
  });

App.Component.ts

import { Component } from '@angular/core';
import { FormBuilder, Validators } from '@angular/forms';
import { UserService } from './user.service';
import { UsernameValidator } from './username-validator';

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss'],
})
export class AppComponent {
  constructor(private fb: FormBuilder, private userService: UserService) {}

  registrationForm = this.fb.group({ 
    username: [
      null,{
      asyncValidators:[UsernameValidator.createValidator(this.userService)],
      updateOn: 'blur'
}
    ],
  });
}

App.Component.html

<mat-form-field>
  <mat-label>Username</mat-label>
  <input matInput placeholder="Enter User Name here" formControlName="username" />
  <mat-error
    *ngIf="form.get('username').hasError('usernameAlreadyExists')"
  >
    Username already <strong>exists</strong>
  </mat-error>
</mat-form-field>

Let's Run the Project

After entering the Existing Name

After entering a Different Name

Summary

In this article, I have discussed about implementation of Async Validation in Angular.