Angular Reactive Forms With Built In Validators Example


Learning Objective


Built-in Validators  

In Angular, we have a list of built-in validators that are commonly used while developing an application.

Angular built-in validators won’t always match the exact use case of your application. so you can create your own custom validator. I would recommend reading this article: Angular Custom Validator


List of built-in validators :

  • required
  • requiredTrue
  • email
  • min
  • max
  • minLength
  • maxLength
  • pattern,
  • nullValidator
  • compose

At the time of writing this article, I am using angular version: 6.1.0. But most of the validators are available after 4.2.0.


Angular Reactive Forms with Validators

Now we’ll learn each validator with an example.

As we are using reactive form validators we should have reactive form setup. If you are new to angular reactive forms, I would recommend reading this article: Angular Reactive Forms

To get the better understanding of all the validators we are going to create one reactive form page and we’ll apply validators to it.

We’ll be using the following files throughout this example:

demo-form.component.html

demo-form.component.ts

The demo-form.component.ts will look as follows, It doesn’t contain any validators right now, but we’ll add it one by one

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

@Component({
selector: 'app-demo-form',
templateUrl: './app-demo-form.component.html',
styleUrls: ['./app-demo-form.component.scss'],
})

export class DemoFormComponent implements OnInit {
form: FormGroup;
submitted:boolean=false;

constructor(private fb: FormBuilder) { }

ngOnInit() {
this.form = this.fb.group({
name: ['']
 });
}

onSubmit() {
this.submitted=true;
 }
}

and demo-form.component.html will look as follows:

<div>
  <h2>Angular Reactive Form Validation</h2>
  <form [formGroup]="form" (ngSubmit)="onSubmit()">
    <div>
      <label>Name</label>
      <input type="text" formControlName="name" />
    </div>
    <div>
      <button>Register</button>
    </div>
  </form>
</div>

Now we’ll add all validators one by one to the demo form.


1) required

Validator that requires the control have a non-empty value.

This validator will set required property to true to the form-control instance if validation fails.

The thing we’ll implement to understand required validator:

  • name field is required

To make the name field as required, we’ll add required validator to the form.


this.form = this.fb.group({
      name: ['', Validators.required]
    });

and in demo-form.component.html, we’ll add validation as following to the input element to show the error if input element invalid.

 <div class="error" *ngIf="form.get('name').hasError('required') && submitted">Name is required</div>

Above code will check two conditions:

  • 1. The input element value is empty.
  • 2. The form is submitted.

If both conditions are true, then it will show the error otherwise, it won’t show the error.

You can see that we have used get('name') method of form-group to get the control of the input element.

and we’ve also used hasError('required') method to check that required error is exist or not for that control because angular will set required property to true to the element when validation fails.

We have also checked submitted variable to check that form has been submitted or not.

demo-form.component.html will look as follow after adding required validators to all fields:

 <div>
  <h2>Angular Reactive Form Validation</h2>
  <form [formGroup]="form" (ngSubmit)="onSubmit()">
    <div>
      <label>Name</label>
      <input type="text" formControlName="name" />
      <div class="error" *ngIf="form.get('name').hasError('required') && submitted">Name is required</div>
    </div>
    <div>
      <button [disabled]="form.invalid">Register</button>
    </div>
  </form>
</div>

2) requiredTrue

Validator that requires the control’s value be true. This validator is commonly used for required checkboxes i.e  accept terms and conditions checkbox.

This validator also set required property to true to the form-control instance if validation fails.

To understand requiredTrue, we’ll add a new field called Accept Terms and Conditions, which will be a checkbox.

so our demo-form.component.ts will look as follows:

   this.form = this.fb.group({
        name: ['', Validators.required],
        tnc:['',Validators.requiredTrue]
      });

and demo-form.component.html file will look as follows:

<div>
<h2>Angular Reactive Form Validation</h2>
<form [formGroup]="form" (ngSubmit)="onSubmit()">
<div>
<label>Name: </label>
<input type="text" formControlName="name" />
<div class="error" *ngIf="form.get('name').hasError('required') && submitted">Name is required</div>
</div>
<div>
<label>Accept Term and Conditions :</label>
<input type="checkbox" formControlName="tnc" />
<div class="error" *ngIf="form.get('tnc').hasError('required') && submitted">You must agree to the terms and conditions </div>
</div>
<div>
<button>Register</button>
</div>
</form>
</div> 

If you will click on Register button it will highlight all the errors.


3) email

Validator that requires the control’s value pass an email validation test.

This validator will set email property to true to the form-control instance if validation fails.

To understand this validator we’ll add a new property called email and we’ll add two validation to it.

  •  required validation
  •  email validation

To use multiple validators in a single field, there is compose validator function which accepts an array of validators.

We can use it as follows:

email:['',Validators.compose([Validators.required,Validators.email])]

demo-form.component.ts will look as follows:

this.form = this.fb.group({
      email:['',Validators.compose([Validators.required,Validators.email])]
    });

and demo-form.component.html will look as follows:

 <div>
      <label>Email: </label>
      <input type="email" formControlName="email" />
      <div class="error" *ngIf="form.get('email').hasError('required') && submitted">Email is required</div>
      <div class="error" *ngIf="form.get('email').hasError('email') && form.get('email').touched">Email is invalid</div>
    </div>

4) min

Validator that requires the control’s value to be greater than or equal to the provided number. The validator exists only as a function.

To understand this validator we’ll take an example of quantity field.

Things we’ll implement:

  • Minimum required quantity is 10.

demo-form.component.ts will look as follows:

this.form = this.fb.group({
      quantity:['',Validators.min(10))]
    });

and demo-form.component.html will look as follows:

<div>
      <label>Quantity: </label>
      <input type="number" formControlName="quantity" />
      <div class="error" *ngIf="form.get('quantity').hasError('min') && submitted">Minimum required quantity is 10</div>
    </div>

We can also update the above code to show the error description so that it’ll get dynamic min value instead of hard-coded 10 as follows.

<div>
      <label>Quantity: </label>
      <input type="number" formControlName="quantity" />
      <div class="error" *ngIf="form.get('quantity').hasError('min') && submitted">Maximum required quantity is {{form.get('quantity').errors?.min?.min}}</div>
    </div>

5) max

Validator that requires the control’s value to be less than or equal to the provided number.

 The validator exists only as a function.

To understand this validator we’ll again take an example of quantity field.

Things we’ll implement:

  • Maximum required quantity is 50.

demo-form.component.ts will look as follows:

this.form = this.fb.group({
      quantity:['',Validators.max(50))]
    });

and demo-form.component.html will look as follows:

 <div>
      <label>Quantity: </label>
      <input type="number" formControlName="quantity" />
      <div class="error" *ngIf="form.get('quantity').hasError('max') && submitted">Maximum required quantity is 50</div>
    </div>

We can also update the above code to show the error description so that it’ll get dynamic max value instead of hard-coded 50 as follows.

 <div>
      <label>Quantity: </label>
      <input type="number" formControlName="quantity" />
      <div class="error" *ngIf="form.get('quantity').hasError('max') && submitted">Maximum required quantity is {{form.get('quantity').errors?.max?.max}}</div>
    </div>


6) minLength

Validator that requires the length of the control’s value to be greater than or equal to

the provided minimum length. This validator is also provided by default if you use the HTML5 `minlength` attribute.

Things we’ll implement to understand minLength validator:

  – the name should be at least 5 characters long.

In the reactive form we’ll add minLength validators to name property as follows:

this.form = this.fb.group({
      name:['',Validators.minLength(5))]
    });

and demo-form.component.html will look as follows:

 <div>
      <label>Name: </label>
      <input type="text" formControlName="name" />
  <div class="error" *ngIf="form.get('name').hasError('minlength') && submitted">Name must be at least 5 characters long.</div>
  </div>

Now, To get the dynamic value of minLength from reactive form,
we can update demo-form.component.html as follows:

 <div>
      <label>Name: </label>
      <input type="text" formControlName="name" />
      <div class="error" *ngIf="form.get('name').hasError('minlength') && submitted">  Name must be at least {{form.get('name').errors?.minlength?.requiredLength}} characters long.</div> 
    </div>

7) maxLength

Validator that requires the length of the control’s value to be less than or equal

to the provided maximum length. This validator is also provided by default if you use the

the HTML5 `maxlength` attribute.

Things we’ll implement to understand maxLength validator:

    – the name can max 12 characters long.

In reactive form we’ll add maxLength validators to name property as follows:

this.form = this.fb.group({
      name:['',Validators.maxLength(5))]
    });

and demo-form.component.html will look as follows:

 <div>
      <label>Name: </label>
      <input type="text" formControlName="name" />
  <div class="error" *ngIf="form.get('name').hasError('maxlength') && submitted">Name can be max 12 characters long.</div>
  </div>

Now, To get the dynamic value of maxLength from reactive form, we can update
demo-form.component.html as follows:

 <div>
      <label>Name: </label>
      <input type="text" formControlName="name" />
      <div class="error" *ngIf="form.get('name').hasError('maxlength') && submitted">  Name can be max {{form.get('name').errors?.maxlength?.requiredLength}} characters long.</div> 
    </div>

8) pattern

Validator that requires the control’s value to match a regex pattern. This validator is also provided by default, if you use the HTML5 `pattern` attribute.

To understand pattern validation, we’ll take an example of username property.

Things we’ll implement:

– username should be at least 8 characters long.

– username can be max 15 characters long.

– only contains alphanumeric characters, underscore and dash.

To satisfy the above conditions we’ll implement regex pattern as follows:

this.form = this.fb.group({
      username:['',Validators.pattern("^[a-z0-9_-]{8,15}$"))]
    });

and demo-form.component.html will look as follows:

 <div>
      <label>Name: </label>
      <input type="text" formControlName="name" />
  <div class="error" *ngIf="form.get('username').hasError('pattern') && submitted">Username is invalid</div>   </div>

9) nullValidator

validator the perform no operation.

It is used when you don’t want to do any validation check on form property.

After all, it has the same effect as you are not defining any validators for the property.


10) compose

Compose multiple validators into a single function that returns the union of the individual error maps for the provided control.

It is used when you want to combine multiple validators for a single property.

To understand we’ll take an example of username.

Things we’ll implement:

– Username should be at least 5 characters long.

– Username can be max 12 characters long.

Here we’ll combine maxLength and minLength validator as follows:

this.form = this.fb.group({
      username:['',Validators.compose([Validators.minLength(5),Validators.maxLength(12)])]
    });

demo-form.component.html will look as follows:

<div>
      <label>Username: </label>
      <input type="text" formControlName="username" />
      <div class="error" *ngIf="form.get('name').hasError('minlength') && submitted">  Name must be at least {{form.get('name').errors?.minlength?.requiredLength}} characters long.</div> 
      <div class="error" *ngIf="form.get('name').hasError('maxlength') && submitted">  Name can be max {{form.get('name').errors?.maxlength?.requiredLength}} characters long.</div>     
    </div>

And that’s it, that’s all the built-in validators are.


Thanks for reading the Angular Reactive Forms with Validators article.

I hope you like this Angular Reactive Forms with Validators article.🙂

Also, read: