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 Promise. In this article, we will create an async validator for the Existing user. We will check the user exists or not using async validator.
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:
- The function must implement the
AsyncValidatorFn
Interface, which defines the signature of the validator function.
- The function should be returned in following observable or promise.
- 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.