Angular FormControl Add and Remove Validators Dynamically
January 16, 2024
On this page we will learn to add and remove sync and async validators dynamically from FormControl
in our Angular application. The FormControl
provides setValidators
and setAsyncValidators
to add validators dynamically. The clearValidators
and clearAsyncValidators
of FormControl
remove validators dynamically. When we add or remove a validator at run time, we need to call updateValueAndValidity()
of FormControl
for the new validation to take effect.
Methods to Add Validators :
Find the methods to add sync and async validators in
FormControl
dynamically.
addValidators() : Adds sync validators without affecting existing validators.
addAsyncValidators() : Adds async validators without affecting existing validators.
setValidators() : Sets the sync validators overwriting the existing sync validators.
setAsyncValidators() : Sets the async validators overwriting the existing async validators.
Methods to Remove Validators :
Find the methods to remove sync and async validators in
FormControl
dynamically.
removeValidators() : Removes the specified sync validators without affecting other validators.
removeAsyncValidators() : Removes the specified async validators without affecting other validators.
clearValidators() : Clears all sync validators.
clearAsyncValidators() : Clears all async validators.
After adding or removing validators, we need to call
updateValueAndValidity()
on that control.
Contents
1. setValidators()
TheFormControl.setValidators
sets the synchronous validators that are active on this control. This method will overwrite any existing sync validators.
Find the method declaration from Angular doc.
setValidators(newValidator: ValidatorFn | ValidatorFn[]): void
FormGroup
.
this.userForm = this.formBuilder.group({ fullName: '', username: ['', [ Validators.required ]] });
get fullName() { return this.userForm.get('fullName'); } get username() { return this.userForm.get('username'); }
fullName
control.
this.fullName.setValidators([Validators.required]); this.fullName.updateValueAndValidity();
setValidators
will first clear all existing sync validators and then add the given sync validators. Make sure to call updateValueAndValidity
after adding validators to take effect the validation.
2. Now we will add validators to
username
control. This control has already required
validator configured. When we add validators using setValidators
, the existing sync validator will be overwritten and only validators configured by setValidators
, will be available. Find the code snippet.
this.username.setValidators([Validators.required, Validators.minLength(5), Validators.maxLength(10)]); this.username.updateValueAndValidity();
username
control will have sync validators as required
, minLength
and maxLength
.
2. clearValidators()
TheFormControl.clearValidators
empties out the sync validator list of this control.
Find the method declaration.
clearValidators(): void
this.fullName.clearValidators(); this.fullName.updateValueAndValidity();
clearValidators()
will clear all sync validators of this control.
3. setAsyncValidators()
TheFormControl.setAsyncValidators
sets the asynchronous validators that are active on this control. This method will overwrite any existing async validators.
Find the method declaration from Angular doc.
setAsyncValidators(newValidator: AsyncValidatorFn | AsyncValidatorFn[]): void
existingUsernameValidator()
. We will use setAsyncValidators
as following.
this.username.setAsyncValidators([existingUsernameValidator(this.userService)]); this.username.updateValueAndValidity();
username
control will be configured with existingUsernameValidator()
async validator. The other existing async validators to this control will be overwritten, if any.
4. clearAsyncValidators()
TheFormControl.setAsyncValidators
empties out the async validator list of this control.
Find the method declaration from Angular doc.
clearAsyncValidators(): void
this.username.clearAsyncValidators(); this.username.updateValueAndValidity();
clearAsyncValidators()
will clear all async validators of this control.
5. addValidators() and removeValidators()
Here we will learn to useaddValidators()
and removeValidators()
method. We can remove validators only using validator reference added to control.
Find the reference to validator that we will add/remove from control.
fnMinLength = Validators.minLength(2);
This validator adds the specified validator or array of specified validators without affecting existing validators.
Find the method declaration from Angular doc.
addValidators(validators: ValidatorFn | ValidatorFn[]): void
this.fullName?.addValidators([this.fnMinLength]); this.fullName?.updateValueAndValidity(); console.log(this.fullName?.hasValidator(this.fnMinLength));
hasValidator()
will return true.
removeValidators() :
This method removes a specified validator or array of specified validators without affecting existing validators.
removeValidators()
removes validators comparing with function reference of validators. We must pass same validator references that have been set or added to control. If the reference does not match, it will be ignored.
Find the method declaration from Angular doc.
removeValidators(validators: ValidatorFn | ValidatorFn[]): void
this.fullName?.removeValidators([this.fnMinLength]); this.fullName?.updateValueAndValidity();
6. addAsyncValidators() and removeAsyncValidators()
Here we will learn to useaddAsyncValidators()
and removeAsyncValidators()
method. We can remove validators only using validator reference added to control.
Find the reference to an async validator that we will add/remove from control.
existingUnValidator = existingUsernameValidator(this.userService);
This method adds specified async validator or array of async validators without affecting the existing validators.
Find the method declaration from Angular doc.
addAsyncValidators(validators: AsyncValidatorFn | AsyncValidatorFn[]): void
this.username?.addAsyncValidators([this.existingUnValidator]); this.username?.updateValueAndValidity(); console.log(this.username?.hasAsyncValidator(this.existingUnValidator));
hasAsyncValidator()
will return true.
removeAsyncValidators() :
This method removes the specified validator reference or its array without affecting existing validators using function references of validators set or added to this control. If the specified validator reference is not found, it is ignored.
Find the method declaration from Angular doc.
removeAsyncValidators(validators: AsyncValidatorFn | AsyncValidatorFn[]): void
this.username?.removeAsyncValidators([this.existingUnValidator]); this.username?.updateValueAndValidity();
7. Complete Example with Reactive Form
reactive-form.component.tsimport { Component, OnInit } from '@angular/core'; import { FormGroup, FormBuilder, Validators, ReactiveFormsModule } from '@angular/forms'; import { UserService } from './user-service'; import { existingUsernameValidator } from './existing-username-validator'; import { CommonModule } from '@angular/common'; @Component({ selector: 'app-reactive', standalone: true, imports: [CommonModule, ReactiveFormsModule], templateUrl: './reactive-form.component.html' }) export class ReactiveFormComponent implements OnInit { userForm!: FormGroup; constructor(private formBuilder: FormBuilder, private userService: UserService) { } ngOnInit() { this.userForm = this.formBuilder.group({ fullName: '', username: ['', [Validators.required]], password: ['', [Validators.required]] }); } get fullName() { return this.userForm.get('fullName'); } get username() { return this.userForm.get('username'); } get password() { return this.userForm.get('password'); } fnMinLength = Validators.minLength(2); existingUnValidator = existingUsernameValidator(this.userService); addValidators() { this.fullName?.addValidators([this.fnMinLength]); this.fullName?.updateValueAndValidity(); console.log(this.fullName?.hasValidator(this.fnMinLength)); } addAsyncValidators() { this.username?.addAsyncValidators([this.existingUnValidator]); this.username?.updateValueAndValidity(); console.log(this.username?.hasAsyncValidator(this.existingUnValidator)); } setValidators() { this.fullName?.setValidators([Validators.required]); this.fullName?.updateValueAndValidity(); this.username?.setValidators([Validators.required, Validators.minLength(5), Validators.maxLength(10)]); this.username?.updateValueAndValidity(); this.password?.setValidators([Validators.required, Validators.minLength(5), Validators.maxLength(15)]); this.password?.updateValueAndValidity(); } setAsyncValidators() { this.username?.setAsyncValidators([existingUsernameValidator(this.userService)]); this.username?.updateValueAndValidity(); } removeValidators() { this.fullName?.removeValidators([this.fnMinLength]); this.fullName?.updateValueAndValidity(); } removeAsyncValidators() { this.username?.removeAsyncValidators([this.existingUnValidator]); this.username?.updateValueAndValidity(); } clearUserValidators() { this.fullName?.clearValidators(); this.fullName?.updateValueAndValidity(); this.username?.clearValidators(); this.username?.updateValueAndValidity(); this.password?.clearValidators(); this.password?.updateValueAndValidity(); } clearUserAsyncValidators() { this.username?.clearAsyncValidators(); this.username?.updateValueAndValidity(); } onFormSubmit() { this.userService.saveUser(this.userForm.value); this.userForm.reset(); } }
<h3>User Form</h3> <form [formGroup]="userForm" (ngSubmit)="onFormSubmit()"> <table> <tr> <td>Full Name: </td> <td> <input formControlName="fullName"> <div *ngIf="fullName?.dirty && fullName?.errors" class="error"> <div *ngIf="fullName?.errors?.['required']"> Full name required. </div> <div *ngIf="fullName?.errors?.['minlength']"> Minimum length should be 2. </div> </div> </td> </tr> <tr> <td>Username: </td> <td> <input formControlName="username"> <div *ngIf="username?.dirty && username?.errors" class="error"> <div *ngIf="username?.errors?.['required']"> Username required. </div> <div *ngIf="username?.errors?.['minlength']"> Minimum length should be 5. </div> <div *ngIf="username?.errors?.['maxlength']"> Maximum length should be 10. </div> <div *ngIf="username?.errors?.['usernameExists']"> Username already exists. </div> </div> </td> </tr> <tr> <td>Password: </td> <td> <input formControlName="password" type="password"> <div *ngIf="password?.dirty && password?.errors" class="error"> <div *ngIf="password?.errors?.['required']"> Password required. </div> <div *ngIf="password?.errors?.['minlength']"> Minimum length should be 5. </div> <div *ngIf="password?.errors?.['maxlength']"> Maximum length should be 15. </div> </div> </td> </tr> <tr> <td colspan="2"> <button [disabled]="userForm.invalid">Submit</button><br /> <button type="button" (click)="addValidators()">Add Sync Validators</button><br /> <button type="button" (click)="addAsyncValidators()">Add Async Validators</button><br /> <button type="button" (click)="setValidators()">Set Sync Validators</button><br /> <button type="button" (click)="setAsyncValidators()">Set Async Validators</button><br /> <button type="button" (click)="removeValidators()">Remove Validators</button><br /> <button type="button" (click)="removeAsyncValidators()">Remove Async Validators</button><br /> <button type="button" (click)="clearUserValidators()">Clear Sync Validators</button><br /> <button type="button" (click)="clearUserAsyncValidators()">Clear Async Validators</button> </td> </tr> </table> </form>
import { AsyncValidatorFn, AbstractControl, ValidationErrors } from '@angular/forms'; import { Observable } from "rxjs"; import { map } from 'rxjs/operators'; import { UserService } from './user-service'; export function existingUsernameValidator(userService: UserService): AsyncValidatorFn { return (control: AbstractControl): Promise<ValidationErrors | null> | Observable<ValidationErrors | null> => { return userService.unameAlreadyExists(control.value).pipe( map(exist => { return exist ? {"usernameExists": true} : null; } )); }; }
export class User { fullName!: string; username!: string; password!: string; }
import { Injectable } from '@angular/core'; import { Observable, of } from 'rxjs'; import { User } from './user'; const USERS = ['mahesh', 'krishna']; @Injectable({ providedIn: 'root' }) export class UserService { unameAlreadyExists(uname: string): Observable<boolean> { if (USERS.indexOf(uname) >= 0) return of(true); else return of(false); } saveUser(user: User) { console.log(user.password); console.log(user.username); console.log(user.password); } }
8. References
Angular FormControlAngular FormBuilder