Angular 2 Form validations and custom validation, How to Implement

angular tutorial

Today, let’s implement angular 2 inbuilt validations and create a custom validation using angular 2 validate interface.

In this tutorial, let’s implement the following angular 2 inbuilt validations and create a custom validation using angular 2 validate interface

  1. Required - The form field is mandatroy
  2. Maxlength - Maximum number of characters in the field.
  3. Minlength - Minimum number of characters in the field.
  4. Pattern - Regular expression to match the input values and validate.
  5. Custom Validator - Writing custom validation function to match password and confirm password fields.

Getting Started

Lets create a form component. I used angular CLI to generate the folder structure and created a form folder for component files. To style we are using bootstrap. The folder structure should look like this :

www.cuppalabs.com

Create Form Component

Following code creates a form component with the input fields. In the next steps, let see how we can apply validations on each of these fields. View Live Demo

  import { Component,Directive, forwardRef, 
           Attribute,OnChanges, SimpleChanges,Input } from '@angular/core';
  import { NG_VALIDATORS,Validator,
           Validators,AbstractControl,ValidatorFn } from '@angular/forms';
  import { User }    from './user';
  @Component({
    moduleId: module.id,
    selector: 'login-form',
    templateUrl: './login-form.component.html',
    styleUrls: ['./login-form.component.css']
  })
  export class LoginFormComponent {
    powers = ['Really Smart', 'Super Flexible',
              'Super Hot', 'Weather Changer'];
    model = new User('','',null,'','','');
    submitted = false;
    onSubmit() { this.submitted = true; }
    newHero() {
    // this.model = new User('','');
    }
  }
    
<div class="col-md-6">
   <h3>Angular 2 Form Validations Demo</h3>
   <form (ngSubmit)="onSubmit()" #loginForm="ngForm">
   <div class="form-group">
      <label for="name">Name</label>
      <input type="text" class="form-control" id="name" #name="ngModel">
   </div>
   <div class="form-group">
      <label for="name">Email Address</label>
      <input type="text" class="form-control" id="emailaddress" #email="ngModel">
   </div>
   <div class="form-group">
      <label for="name">Mobile Number</label>
      <input type="text" class="form-control" id="mobilenumber" #mobile="ngModel">
   </div>
   <div class="form-group">
      <label for="name">Password</label>
      <input type="password" class="form-control" id="password" #password="ngModel">
   </div>
   <div class="form-group">
      <label for="name">Confirm Password</label>
      <input type="password" class="form-control" id="confirmPassword" #confirmPassword="ngModel">
   </div>
   <button type="submit" class="btn btn-success btn-block" [disabled]="!loginForm.form.valid">Submit</button>
   </form>
</div>
      
    import { Directive, forwardRef, Attribute } from '@angular/core';
    import { NG_VALIDATORS,Validator,
             Validators,AbstractControl,ValidatorFn } from '@angular/forms';

    @Directive({
        selector: '[validateEqual][formControlName],[validateEqual][formControl],
                   [validateEqual][ngModel]',
        providers: [
                    { provide: NG_VALIDATORS, 
                      useExisting: forwardRef(() => EqualValidator),
                      multi: true }
                   ]
    })
    export class EqualValidator implements Validator {
        constructor( @Attribute('validateEqual') public validateEqual: string) {}

        validate(c: AbstractControl): { [key: string]: any } {
            // self value (e.g. retype password)
            let v = c.value;

            // control value (e.g. password)
            let e = c.root.get(this.validateEqual);

            // value not equal
            if (e && v !== e.value) return {
                validateEqual: false
            }
            return null;
        }
    }
    
export class User{
    constructor(
        public name:string,
        public email: string,
        public mobile: number,
        public gender: string,
        public password: any,
        public confirmPassword: any
    ){}
}      
    

Once we have created the form, it looks like something below.

www.cuppalabs.com

Now it’s time for us to apply the validations on each field.

First Name Validation

Requirement - Required and only alphabets allowed in the name field.

  • required attribute on input tag ensures that the filed value is mandatory.
  • pattern="[a-zA-Z][a-zA-Z ]+" attribute take a regex to check for only characters in the field.
  • [a-zA-Z][a-zA-Z ]+ is the regular expression to check for only alphabets.
  • name.valid is a boolean value to check if the field has any error on the validation attributes.
  • name.hasError('required')" returns true if the value is not entered.
  • name.hasError('pattern')" return true if the entered value does not match with the regular expression.

Based on the type of error, whether on required or on pattern attributes, the error messages are shown and hidden.

<div class="form-group">
   <label for="name">Name</label>
   <input type="text" class="form-control" id="name"
   required
   pattern="[a-zA-Z][a-zA-Z ]+"
   [(ngModel)]="model.name" name="name"
   #name="ngModel">
   <div [hidden]="name.valid || name.pristine"
      class="alert alert-danger">
      <div [hidden]="!name.hasError('required')">Name is required</div>
      <div [hidden]="!name.hasError('pattern')">Only alphabetsallowed</div>
   </div>
</div>
 

Email Address Validation

Requirement - Validate the email format joe@gmail.com. Entered email should be having valid email with @, .co or.com.

  • required attribute on input tag ensures that the filed value is mandatory.
  • pattern="^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$" takes regular expression ^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$ to check for valid email.
<div class="form-group">
<label for="name">Email Address</label>
<input type="text" class="form-control" id="emailaddress"
required
[(ngModel)]="model.email" name="email"
pattern="^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$" 
#email="ngModel">
<div [hidden]="email.valid || email.pristine"
   class="alert alert-danger">
   <div [hidden]="!email.hasError('required')">Email is required</div>
   <div [hidden]="!email.hasError('pattern')">Email format should be 
      <small><b>joe@abc.com</b></small>
   </div>
</div>

Mobile Number Validation

Requirement - Should be only numbers and should have 10 digits only.

  • required attribute on input tag ensures that the filed value is mandatory.
  • pattern="[0-9]*" take regular expression [0-9]* to allow only numbers.
  • minlength="10" minlength of the input value should be 10.
  • maxlength="10" max length of the input value should be 10. Based on the type of error in each of the attributes above, the error messages are shown.
<div class="form-group">
   <label for="name">Mobile Number</label>
   <input type="text" class="form-control" id="mobilenumber"
   required
   [(ngModel)]="model.mobile" name="mobilenumber"
   pattern="[0-9]*"
   minlength="10"
   maxlength="10" 
   #mobile="ngModel">
   <div [hidden]="mobile.valid || mobile.pristine"
      class="alert alert-danger">
      <div [hidden]="!mobile.hasError('minlength')">Mobile should be 10digit</div>
      <div [hidden]="!mobile.hasError('required')">Mobile is required</div>
      <div [hidden]="!mobile.hasError('pattern')">Mobile numberr should be only numbers</div>
   </div>
</div>  
 

Password Matching Validation

Angular 2 does not provide any inbuilt validator to match password. We need to write a custom directive to validate password match. Let’s write the directive using the validator interface.

import { Directive, forwardRef, Attribute } from '@angular/core';
import { NG_VALIDATORS,Validator,
         Validators,AbstractControl,ValidatorFn } from '@angular/forms';

@Directive({
    selector: '[validateEqual][formControlName],[validateEqual][formControl],[validateEqual][ngModel]',
    providers: [
        { provide: NG_VALIDATORS, useExisting: forwardRef(() => EqualValidator), multi: true }
    ]
})
export class EqualValidator implements Validator {
    constructor( @Attribute('validateEqual') public validateEqual: string) {}

    validate(c: AbstractControl): { [key: string]: any } {
        // self value (e.g. retype password)
        let v = c.value;

        // control value (e.g. password)
        let e = c.root.get(this.validateEqual);

        // value not equal
        if (e && v !== e.value) return {
            validateEqual: false
        }
        return null;
    }
}
 

The EqualValidator directive needs to be added to the html code as shown below.

  • validateEqual="password" in which password is the name of the field whose value is to be matched.
<div class="form-group">
   <label for="name">Password</label>
   <input type="password" class="form-control" id="password"
   required
   [(ngModel)]="model.password" name="password"
   #password="ngModel">
   <div [hidden]="password.valid || password.pristine"
      class="alert alert-danger">
      Password is required
   </div>
</div>
<div class="form-group">
   <label for="name">Confirm Password</label>
   <input type="password" class="form-control" id="confirmPassword"
   required
   validateEqual="password"
   [(ngModel)]="model.confirmPassword" name="confirmPassword"
   #confirmPassword="ngModel">
   <div [hidden]="confirmPassword.valid || confirmPassword.pristine"
      class="alert alert-danger">
      Passwords did not match
   </div>
</div>
 

That’s all folks !!

Pradeep Terli

Web UI Developer, Blogger, Thinker , Entrepreneur. Loves to explore technology with focus on web technologies.