Creating Custom Validators In Reactive Forms Using Angular 6

Avakash Dekavadiya

Validating user input for accuracy and completeness helps in improving overall data quality. Angular and its form package turns up with a Validators class that has some beneficial validators like minLength, maxLength, required and pattern. However, occasionally if we wish to validate different fields under more complex/custom rules we can make optimum use of custom validator.

Defining custom validators while using Reactive Forms in Angular comes very easy as they are more of regular functions. One can conveniently generate function for custom validators within the component file in case the validator is not supposed to be used elsewhere. But, herein we will be assuming the re-use and create respective validators in separate files.

Consider the following example:[Step 1: Create a project and add material library

Ng new ng6material

Cd ng6mateial

Ng add @angular/material

Ng serve

Step 2: Create component called reactiveform.component.ts

Ng generate component reactiveform

Configure route of reactiveform.component.ts so that we can navigate it at http://localhost:4200/reactive-form

Step 3: Create a simple form with a model using Angular material and @angular/form

import { Component, OnInit } from '@angular/core';
import{FormBuilder,FormGroup} from '@angular/forms';

@Component({
 selector: 'app-login',
 templateUrl: './reactiveform.component.html',
 styleUrls: ['./reactiveform.component.css']
})

export class ReactiveformComponent implements OnInit {
 complexForm : FormGroup;
 constructor(fb:FormBuilder) {
   this.complexForm = fb.group({
     userName:””,
     email:””,
     passWord:””,
   })
 }
 ngOnInit() {}
 submitForm(value: any){
   console.log(value);
 }
}
<div class="login-wrapper">
<mat-card>
 <div style="text-align:center;">
   <img src="https://aimdek-s3-uploads.s3.ap-south-1.amazonaws.com/wp-content/uploads/2016/12/height_70px.png">
 </div>
 <form class="example-form" [formGroup]="complexForm" (ngSubmit)="submitForm(complexForm.value)">
   <mat-form-field>
     <input matInput placeholder="Username" [formControl]="complexForm.controls['userName']" />
   </mat-form-field>
   <br>
   <mat-form-field>
       <input matInput placeholder="email" [formControl]="complexForm.controls['email']" />
   </mat-form-field>
     <br>
   <mat-form-field >
     <input matInput placeholder="Password"  [formControl]="complexForm.controls['passWord']" />
   </mat-form-field>
   <br>
   <button type="submit" mat-raised-button color="primary" align="right">Login</button>
 </form>
</mat-card>
</div>

This will generate the simple model driven reactive form without in build and custom validation.Now we will add in build validation first and then will go through the custom validation.

For validation we need to import Validators from the @angular/forms and have to add that particular Validators in each field of model.

We are going to use Validators.required and Valodators.email in this demo.

Following snippet shows the usage of build in Validators.Reactiveform.component.ts

import { Component, OnInit } from '@angular/core';
import{FormBuilder,FormGroup,Validators,AbstractControl} from '@angular/forms';

@Component({
 selector: 'app-login',
 templateUrl: './reactiveform.component.html',
 styleUrls: ['./reactiveform.component.css']
})

export class ReactiveformComponent implements OnInit {
 complexForm : FormGroup;
 constructor(fb:FormBuilder) {
   this.complexForm = fb.group({
     userName:[null,Validators.required],
     email:[null,[Validators.required,Validators.email]],
     passWord:[null,[Validators.required]],
   })
 }
 ngOnInit() {}
 submitForm(value: any){
   console.log(value);
 }
}
<div class="login-wrapper">
<mat-card>
 <div style="text-align:center;">
   <img src="https://aimdek-s3-uploads.s3.ap-south-1.amazonaws.com/wp-content/uploads/2016/12/height_70px.png">
 </div>
 <form class="example-form" [formGroup]="complexForm" (ngSubmit)="submitForm(complexForm.value)">
   <mat-form-field [ngClass]="{'has-error':!complexForm.controls['userName'].valid}">
     <input matInput placeholder="Username" [formControl]="complexForm.controls['userName']" />
   </mat-form-field>
   <br>
   <mat-form-field [ngClass]="{'has-error':!complexForm.controls['email'].valid}">
       <input matInput placeholder="email" [formControl]="complexForm.controls['email']" />
   </mat-form-field>
     <br>
   <mat-form-field [ngClass]="{'has-error':!complexForm.controls['passWord'].valid}">
     <input matInput placeholder="Password"  [formControl]="complexForm.controls['passWord']" />
   </mat-form-field>
   <br>
   <button type="submit" mat-raised-button color="primary" align="right" [disabled]="!complexForm.valid">Login</button>
 </form>
</mat-card>
</div>

In this we are getting observable of Validator in html template and from that we can get boolean value whether the field is valid or not

In above case are getting boolead of valid state from the complexForm object of formGroup which we have created in reactiveform.component.ts and check valid state as following:-

complexForm.valid
complexForm.controls['email'].valid

Step 4: Generate custom validator for password

For this we have to create password.validator.ts manually because angular CLI is not providing this in it’s package.

In this file we have to import abstractValidator which is also part of @angular/form package.

Following is the snnipet code of password.validator.ts

import { AbstractControl,Validator } from '@angular/forms';
export function ValidatePassword(control: AbstractControl) {
 if (!/^(?=.*[A-Za-z])(?=.*\d)[A-Za-z\d]{4,20}/.test(control.value)) {
   return { validPassword: true };
 }
 return null;
 }

This code will return boolean if password is valid and return NULL if it is not

Now import this validator in reactiveform.component.ts as following.

import { ValidatePassword } from '../validators/password.validator';

Use the ValidatePassword function along with Validator.required in password field of form model as following:

passWord:[null,[Validators.required,ValidatePassword]],

Now we have to use this in reactiveform.component.html inorder to display custom error message for password as following:-

<div class="error"
       *ngIf="complexForm.get('passWord').errors &&
             complexForm.get('passWord').dirty &&
             complexForm.get('passWord').errors.validPassword">
         Password must contain letter and digit.
</div>

And there you have it: how to create a custom validator for Angular Reactive Forms. We at AIMDek cater future-proof front-end development services. Get in touch with us at hello@aimdek.com for any queries. 

Top E-Commerce Trends In 2018
How does PLM help in managing next-generation product complexity?

Leave a Reply

Your email address will not be published. Required fields are marked *

TALK TO OUR SUBJECT MATTER EXPERT