Skip to content

Lab 04: Async Validator

step-3-album-wholesale-v16-post-add-album-form-array

Continue from your Lab 03 result. If you need a fresh copy, use step-3-album-wholesale-v16-post-add-album-form-array as your base and complete Lab 03 first.

In this lab, you’ll build an asynchronous validator that checks if an album already exists by making HTTP requests. You’ll use RxJS operators like debounceTime and switchMap to optimize the validation, and display loading states during async validation.

Create an async validator that returns an Observable.

The AlbumService exposes isArtistExist(name) and isAlbumExist(artist, name). Use whichever matches your form. This example validates the artist field:

import { AbstractControl, AsyncValidatorFn } from '@angular/forms';
import { of } from 'rxjs';
import { map, debounceTime, switchMap } from 'rxjs/operators';
import { AlbumService } from '../services/album.service';
export function artistExistsValidator(albumService: AlbumService): AsyncValidatorFn {
return (control: AbstractControl) => {
if (!control.value) return of(null);
return of(null).pipe(
debounceTime(300),
switchMap(() => albumService.isArtistExist(control.value)),
map(exists => exists ? { artistExists: true } : null)
);
};
}

Add async validator as third parameter:

albumForm = this.fb.group({
artist: ['', [Validators.required], [artistExistsValidator(this.albumService)]]
});

Display loading indicator:

<span *ngIf="albumForm.get('name')?.pending">
Checking...
</span>
<mat-error *ngIf="albumForm.get('artist')?.errors?.['artistExists']">
Artist already exists
</mat-error>