...
Angular JS, Tutorials

How to create custom form validators using regular expressions in Angular 6

24 January 2019

Here is a custom file which consists of our custom validation examples such as URL, phone number, US zip code, password, US social security number, etc.

I prefer to name this file is ‘custom.validator.ts’, but you can name it whatever and fit this file where you want.

export class CustomValidator {

// Validates URL
static urlValidator(url): any {
   if (url.pristine) {
      return null;
   }

   const URL_REGEXP = /^(http?|ftp|https):\/\/([a-zA-Z0-9.-]+(:[a-zA-Z0-9.&%$-]+)*@)*((25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9][0-9]?)(\.(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])){3}|([a-zA-Z0-9-]+\.)*[a-zA-Z0-9-]+\.(com|edu|gov|int|mil|net|org|biz|arpa|info|name|pro|aero|coop|museum|[a-zA-Z]{2}))(:[0-9]+)*(\/($|[a-zA-Z0-9.,?'\\+&%$#=~_-]+))*$/;

   url.markAsTouched();

   if (URL_REGEXP.test(url.value)) {
      return null;
   }

   return {
      invalidUrl: true
   };
}

// Validates passwords
static matchPassword(group): any {
   const password = group.controls.password;
   const confirm = group.controls.confirm;

   if (password.pristine || confirm.pristine) {
      return null;
   }

   group.markAsTouched();

   if (password.value === confirm.value) {
      return null;
   }

   return {
      invalidPassword: true
   };
}

// Validates numbers
static numberValidator(number): any {
   if (number.pristine) {
      return null;
   }

   const NUMBER_REGEXP = /^-?[\d.]+(?:e-?\d+)?$/;

   number.markAsTouched();

   if (NUMBER_REGEXP.test(number.value)) {
      return null;
   }

   return {
      invalidNumber: true
   };
}

// Validates US SSN
static ssnValidator(ssn): any {
   if (ssn.pristine) {
      return null;
   }

   const SSN_REGEXP = /^(?!219-09-9999|078-05-1120)(?!666|000|9\d{2})\d{3}-(?!00)\d{2}-(?!0{4})\d{4}$/;

   ssn.markAsTouched();

   if (SSN_REGEXP.test(ssn.value)) {
      return null;
   }

   return {
      invalidSsn: true
   };
}

// Validates US phone numbers
static phoneValidator(number): any {
   if (number.pristine) {
      return null;
   }

   const PHONE_REGEXP = /^(\([0-9]{3}\) |[0-9]{3}-)[0-9]{3}-[0-9]{4}$/;

   number.markAsTouched();

   if (PHONE_REGEXP.test(number.value)) {
      return null;
   }

   return {
      invalidNumber: true
   };
}

// Validates zip codes
static zipCodeValidator(zip): any {
   if (zip.pristine) {
      return null;
   }

   const ZIP_REGEXP = /^[0-9]{5}(?:-[0-9]{4})?$/;

   zip.markAsTouched();

   if (ZIP_REGEXP.test(zip.value)) {
      return null;
   }

   return {
      invalidZip: true
   };
}

}

First you have to import this file in your component file like this:

import { FormBuilder, Validators, FormGroup } from '@angular/forms';
import { CustomValidator } from '../../shared/custom.validator'; // here you can write your own validation file path

Now, the form is ready to be initiated. The following example will throw an alert if the input numberInput is empty and it will accept numbers only, meaning that you will also get an alert if you type characters that are not numbers.

ngOnInit() {
   this.formName = this.fb.group({
      numberInput: ['', [Validators.required, CustomValidator.numberValidator]]
   });
}

Note: Here ‘CustomValidator’ is a class of your validation file which is imported in your component file and ‘numberValidator’ is static method of your validation file.

Last but not least, let’s add an html part of the component:

<form (ngSubmit)="submit(formName)" [formGroup]="formName">
   <div class="form-group">
      <div class="row">
         <div class="col-md-12">
            <input formControlName="numberInput" type="text">
         </div>
      </div>
   </div>

   <small class="form-text text-muted" *ngIf="formName.get('numberInput').touched && formName.get('numberInput').hasError('required')">This field is required!</small>

   <small class="form-text text-muted" *ngIf="formName.get('numberInput').touched && formName.get('numberInput').hasError('invalidNumber')">Numbers accepted only!</small>

   <button type="submit" class="btn btn-primary" [disabled]="formName.invalid">Submit</button>
</form>

Leave a Comments