Skip to main content

Lab 04: Async Validator

πŸ“– Resources​

πŸš€ Starter Code​

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.

πŸ“ Instructions​

Step 1: Create Async Validator​

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)
);
};
}

Step 2: Apply to FormControl​

Add async validator as third parameter:

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

Step 3: Show Pending State​

Display loading indicator:

<span *ngIf="albumForm.get('name')?.pending">
Checking...
</span>

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