Async Validator In Angular
In this article, We will learn how to make a custom async validator in Angular. The process of generating an async validator is quite similar to the process of building Sync validators. The main distinction is that async Validators must produce an observable as a consequence of the validation (or as a Promise).
As with sync validators, Angular does not have any built-in async validators. However, it is very simple to construct one.
How to Create Async Validator
Creating an async validator is as simple as writing a function that follows the rules below.
The AsyncValidatorFn Interface, which defines the signature of the validator function, must be implemented by the function.
Either an observable or a promise must be returned by the function.
If the input is valid, return null; otherwise, return ValidationErrors.
AsyncValidatorFn
The AsyncValidatorFn is an interface that defines the validator function's signature.
interface AsyncValidatorFn { (control: AbstractControl): Promise<validationerrors null=""> | Observable<validationerrors null=""> }
Async Validator Example
import { AbstractControl, ValidationErrors } from '@angular/forms' import { Observable, of } from 'rxjs'; export function gte(control: AbstractControl): Observable<validationerrors> | null { const v:number=+control.value; console.log(v) if (isNaN(v)) { return of({ 'gte': true, 'requiredValue': 10 }) } if (v <= 10) { return of({ 'gte': true, 'requiredValue': 10 }) } return of(null) }
Using the Async Validator
import { gte } from './gte.validator';
As seen below, add the validator to FormControl's Async Validator collection. The async validator is FormControl's third argument.
myForm = new FormGroup({ numVal: new FormControl('', [gte]), })
That is all there is to it. The whole code for app.component.ts is shown below.
import { Component } from '@angular/core'; import { FormGroup, FormControl } from '@angular/forms' import { gte } from './gte.validator'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) export class AppComponent { constructor() { } myForm = new FormGroup({ numVal: new FormControl('',null, [gte]), }) get numVal() { return this.myForm.get('numVal'); } onSubmit() { console.log(this.myForm.value); }
The following code is the complete code of the app.component.html file
<h1>Async Validator in Angular</h1> <h2>Reactive Form</h2> <form autocomplete="off" formgroup="" myform="" ngsubmit="" novalidate="" onsubmit=""> <div> <label>Number :</label> <input formcontrolname="numVal" id="numVal" name="numVal" type="text" /> <div ngif="!numVal.valid && (numVal.dirty ||numVal.touched)"> <div ngif="numVal.errors.gte"> The number should be greater than {{numVal.errors.requiredValue}} </div> </div> </div> <p>Is Form Valid : {{myForm.valid}} </p> <p> <button disabled="" myform.valid="" type="submit">Submit</button> </p> </form>
The following code is the complete code of the app.module.ts file
import { BrowserModule } from '@angular/platform-browser'; import { NgModule } from '@angular/core'; import { ReactiveFormsModule } from '@angular/forms'; import { AppComponent } from './app.component'; @NgModule({ declarations: [ AppComponent ], imports: [ BrowserModule, ReactiveFormsModule ], providers: [], bootstrap: [AppComponent] }) export class AppModule { }
The use case for Async Validators
import { AbstractControl, ValidationErrors } from '@angular/forms' import { Observable, pipe } from 'rxjs'; import { map, debounceTime } from 'rxjs/operators'; export function validate(control: AbstractControl): Observable<validationerrors> | null { const value: string = control.value; return this.http.get(this.baseURL + 'checkIfValid/?value=' + value) .pipe( debounceTime(500), map( (data:any) => { if (!data.isValid) return ({ 'InValid': true }) }) ) }