Swiftorial Logo
Home
Swift Lessons
Matchups
CodeSnaps
Tutorials
Career
Resources

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!