Asynchronous Validators in Angular
Asynchronous validators in Angular allow you to perform server-side or other asynchronous validation checks. This tutorial covers the basics of creating and using asynchronous validators effectively in your Angular applications.
What are Asynchronous Validators?
Asynchronous validators are functions that perform validation asynchronously, typically involving server-side checks or other delayed operations. They return a Promise or an Observable that resolves to either null
(if validation passes) or a validation error object (if validation fails).
Creating an Asynchronous Validator
Here is an example of an asynchronous validator function that checks if a username is already taken:
// app.component.ts
import { Component } from '@angular/core';
import { FormBuilder, FormGroup, Validators, AbstractControl, ValidationErrors } from '@angular/forms';
import { Observable, of } from 'rxjs';
import { delay, map } from 'rxjs/operators';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
userForm: FormGroup;
constructor(private fb: FormBuilder) {
this.userForm = this.fb.group({
username: ['', [Validators.required], [this.usernameValidator]]
});
}
usernameValidator(control: AbstractControl): Observable {
const forbiddenUsernames = ['admin', 'user', 'test'];
return of(forbiddenUsernames.includes(control.value) ? { usernameTaken: true } : null).pipe(
delay(1000)
);
}
onSubmit() {
console.log('Form submitted!', this.userForm.value);
}
}
// app.component.html
<form [formGroup]="userForm" (ngSubmit)="onSubmit()">
<div>
<label for="username">Username</label>
<input type="text" id="username" formControlName="username">
<div *ngIf="userForm.get('username').invalid && userForm.get('username').touched">
<div *ngIf="userForm.get('username').errors.required">Username is required</div>
<div *ngIf="userForm.get('username').errors.usernameTaken">Username is already taken</div>
</div>
</div>
<button type="submit" [disabled]="userForm.invalid">Submit</button>
</form>
Combining Synchronous and Asynchronous Validators
You can combine synchronous and asynchronous validators on a single form control:
// app.component.ts
import { Component } from '@angular/core';
import { FormBuilder, FormGroup, Validators, AbstractControl, ValidationErrors } from '@angular/forms';
import { Observable, of } from 'rxjs';
import { delay, map } from 'rxjs/operators';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
userForm: FormGroup;
constructor(private fb: FormBuilder) {
this.userForm = this.fb.group({
email: ['', [Validators.required, Validators.email], [this.emailValidator]]
});
}
emailValidator(control: AbstractControl): Observable {
const forbiddenEmails = ['test@example.com', 'admin@example.com'];
return of(forbiddenEmails.includes(control.value) ? { emailTaken: true } : null).pipe(
delay(1000)
);
}
onSubmit() {
console.log('Form submitted!', this.userForm.value);
}
}
// app.component.html
<form [formGroup]="userForm" (ngSubmit)="onSubmit()">
<div>
<label for="email">Email</label>
<input type="email" id="email" formControlName="email">
<div *ngIf="userForm.get('email').invalid && userForm.get('email').touched">
<div *ngIf="userForm.get('email').errors.required">Email is required</div>
<div *ngIf="userForm.get('email').errors.email">Invalid email format</div>
<div *ngIf="userForm.get('email').errors.emailTaken">Email is already taken</div>
</div>
</div>
<button type="submit" [disabled]="userForm.invalid">Submit</button>
</form>
Key Points
- Asynchronous validators perform validation checks that require asynchronous operations, such as server-side checks.
- They return a Promise or an Observable that resolves to either
null
(if validation passes) or a validation error object (if validation fails). - Asynchronous validators can be combined with synchronous validators for comprehensive validation.
- Display validation messages conditionally based on the form control's state.
Conclusion
Asynchronous validators in Angular provide a powerful way to handle complex validation scenarios that require delayed operations or server-side checks. By understanding and using asynchronous validators effectively, you can enhance the robustness and user-friendliness of your forms. Happy coding!