Angular FormControl Add and Remove Validators Dynamically
December 15, 2020
This page will walk through Angular FormControl
add and remove validators dynamically. 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.
Contents
1. Technologies Used
Find the technologies being used in our example.1. Angular 11.0.3
2. Node.js 12.5.0
3. NPM 6.9.0
2. 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
.
3. 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.
4. 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.
5. 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.
6. Complete Example with Reactive Form
reactive-form.component.tsimport { Component, OnInit } from '@angular/core'; import { FormGroup, FormBuilder, Validators } from '@angular/forms'; import { UserService } from './user-service'; import { existingUsernameValidator } from './existing-username-validator'; @Component({ selector: 'app-reactive-form', 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'); } addValidators() { 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(); } addAsyncValidators() { this.username.setAsyncValidators([existingUsernameValidator(this.userService)]); 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> </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)="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); } }
import { Component } from '@angular/core'; @Component({ selector: 'app-root', template: ` <app-reactive-form></app-reactive-form> ` }) export class AppComponent { }
table { border-collapse: collapse; } table, th, td { border: 1px solid black; } .error { color: red; } .success { color: green; }
import { NgModule } from '@angular/core'; import { BrowserModule } from '@angular/platform-browser'; import { ReactiveFormsModule } from '@angular/forms'; import { AppComponent } from './app.component'; import { ReactiveFormComponent } from './reactive-form.component'; @NgModule({ imports: [ BrowserModule, ReactiveFormsModule, ], declarations: [ AppComponent, ReactiveFormComponent ], providers: [ ], bootstrap: [ AppComponent ] }) export class AppModule { }
7. Run Application
To run the application, find the steps.1. Download source code using download link given below on this page.
2. Use downloaded src in your Angular CLI application. To install Angular CLI, find the link.
3. Run ng serve using command prompt.
4. Access the URL http://localhost:4200
Find the print screen of the output.

8. References
Angular FormControlAngular FormBuilder