Angular17 min read
Reactive Forms: Async Validators (Email Uniqueness)
Validate input using an API call, like checking if an email is already taken.
Liam Turner
August 3, 2025
3.8k106
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.
#Angular#Forms#Advanced