Reactive Forms: Async Validators (Email Uniqueness)
Validate input using an API call, like checking if an email is already taken.
Async validators are perfect when validation depends on server data. Example: - email already exists - username already taken - coupon code valid ## Step 1: Create an async validator ```ts import { AbstractControl, AsyncValidatorFn } from '@angular/forms'; import { debounceTime, map, of, switchMap } from 'rxjs'; import { inject } from '@angular/core'; import { UsersApi } from './users.api'; export const emailAvailableValidator = (): AsyncValidatorFn => { const api = inject(UsersApi); return (control: AbstractControl) => { if (!control.value) return of(null); return of(control.value).pipe( debounceTime(400), switchMap(email => api.checkEmail(email)), map(res => (res.available ? null : { emailTaken: true })) ); }; }; ``` Assume backend returns: `{ available: true | false }` ## Step 2: Use it on a control ```ts email: new FormControl('', { nonNullable: true, validators: [Validators.required, Validators.email], asyncValidators: [emailAvailableValidator()], }) ``` ## Step 3: Show message in UI ```html <div *ngIf="form.controls.email.errors?.['emailTaken']"> This email is already registered. </div> ``` ## Important performance tip Always debounce async validators, otherwise you spam the API on every keystroke. > Next: Custom form controls with ControlValueAccessor.