Menu

Angular 2 creating a common validation service to be used across all the Angular 2 Reactive forms

Every day we come across web forms and we will have to do many validations, to check if user is entering the collect data, in correct format. Easiest way to do this is to have a service to do all your validations and we can keep on improving this validation service as we go and end of the project we will have a complete validation service to use in next project.

This is my ValidationService.ts

import { Injectable } from '@angular/core';

@Injectable()
export class ValidationService {  
  static getValidatorErrorMessage(validatorName: string, validatorValue?: any) {
        let config = {
            'required': 'Required',
            'invalidCreditCard': 'Is invalid credit card number',
            'invalidEmailAddress': 'Invalid email address',
			'invalidPhone': 'Invalid phone number',
			'invalidPostcode': 'Invalid post code',
			'invalidAlphanumeric': 'Only alphanumeric allowed',
            'invalidPassword': 'Invalid password. Password must be at least 6 characters long, and contain a number.',
            'minlength': `Minimum length ${validatorValue.requiredLength}`
        };

        return config[validatorName];
    }

    static creditCardValidator(control) {
        // Visa, MasterCard, American Express, Diners Club, Discover, JCB
        if (control.value.match(/^(?:4[0-9]{12}(?:[0-9]{3})?|5[1-5][0-9]{14}|6(?:011|5[0-9][0-9])[0-9]{12}|3[47][0-9]{13}|3(?:0[0-5]|[68][0-9])[0-9]{11}|(?:2131|1800|35\d{3})\d{11})$/)) {
            return null;
        } else {
            return { 'invalidCreditCard': true };
        }
    }

    emailValidator(control) {
        // RFC 2822 compliant regex
        if (control.value.match(/[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?/)) {
            return null;
        } else {
            return { 'invalidEmailAddress': true };
        }
    }

    phoneValidator(control) {      
        if (control.value.match(/^[0-9]{1,10}$/)) {
            return null;
        } else {
            return { 'invalidPhone': true };
        }
    }

    postcodeValidator(control) {      
        if (control.value.match(/^[0-9]{1,4}$/)) {
            return null;
        } else {
            return { 'invalidPostcode': true };
        }
    }

    alphanumericValidator(control) {      
        if (control.value.match("^[a-zA-Z0-9_]*$")) {
            return null;
        } else {
            return { 'invalidAlphanumeric': true };
        }
    }  


    static passwordValidator(control) {
        // {6,100}           - Assert password is between 6 and 100 characters
        // (?=.*[0-9])       - Assert a string has at least one number
        if (control.value.match(/^(?=.*[0-9])[a-zA-Z0-9!@#$%^&*]{6,100}$/)) {
            return null;
        } else {
            return { 'invalidPassword': true };
        }
    }
}

In your form obviously you will have to dependency inject this service, then you can initialise the form like below.

this.fb.group({
     preferredName: ['', [Validators.required, this.validationService.alphanumericValidator]],
     postcode: ['', [Validators.required, this.validationService.postcodeValidator]],
     mobile: ['', [Validators.required, this.validationService.phoneValidator]],
     email: ['', [Validators.required, this.validationService.emailValidator]],
});

Happy validation.

Leave a comment