Validations In Reactive Forms In Angular
In this article, We will learn how angular reactive forms validation works. Validation is one of the most common tasks undertaken when creating a form. We will demonstrate how to create Reactive Forms and use built-in validators. In the following article, We will learn how to use Reactive Forms to develop custom validators.
In the Template-driven Forms article, we looked at how validation works. The majority of the principles covered in that tutorial apply here as well.
Validators in Reactive Forms
What is a Validator
A Validator is a function that checks and returns a list of errors for a FormControl, FormGroup, or FormArray instance. Validation has passed if the Validator returns a null value.
How to add a Validator to Reactive Forms
The validators are set as the second and third arguments in the component class's FormControl, FormGroup, or FormArray. A collection of sync validators is the second argument, and a collection of async validators is the third.
Validation is performed and results are returned promptly by sync validators. If no errors are discovered, they either return null or a list of errors.
Validators that are asynchronous: return a Promise or an Observable. If no errors are discovered, they either return null or a list of errors.
Built-in Validators
The Angular ReactiveForms Module comes with a number of built-in validators. They are required, including minlength, maxlength, and pattern, among other things.
Reactive Forms Validation Example
In the previous tutorial, W learned how to develop Angular Reactive Forms. To that example, we'll now add some of the built-in validators.
Model
The contactForm model from the last instruction is shown here.
contactForm = new FormGroup({
firstname: new FormControl(''),
lastname: new FormControl(''),
email:new FormControl(''),
gender: new FormControl(''),
isMarried: new FormControl(''),
country: new FormControl(''),
address:new FormGroup({
city: new FormControl(''),
street: new FormControl(''),
pincode:new FormControl('')
})
})
Disabling the Browser validation
<form contactform="" formgroup="" ngsubmit="" novalidate="" onsubmit="">
Adding in Built-in Validators
Required Validator
firstname: new FormControl('',[Validators.required]),
Minlength Validator
firstname: new FormControl('',[Validators.required,Validators.minLength(10)]),
Maxlength Validator
lastname: new FormControl('',[Validators.maxLength(15)]),
Pattern Validator
lastname: new FormControl('',[Validators.maxLength(15), Validators.pattern("^[a-zA-Z]+$")]),
Email Validator
email:new FormControl('',[Validators.email,Validators.required]),
Our final contactForm will look like this after we've added all of the validators.
contactForm = new FormGroup({
firstname: new FormControl('',[Validators.required,Validators.minLength(10)]),
lastname: new FormControl('',[Validators.required, Validators.maxLength(15), Validators.pattern("^[a-zA-Z]+$")]),
email:new FormControl('',[Validators.email,Validators.required]),
gender: new FormControl('',[Validators.required]),
isMarried: new FormControl('',[Validators.required]),
country: new FormControl('',[Validators.required]),
address:new FormGroup({
city: new FormControl('',[Validators.required]),
street: new FormControl('',[Validators.required]),
pincode:new FormControl('',[Validators.required])
})
})
Disable Submit button
<button contactform.valid="" disabled="" type="submit">Submit</button>
Displaying the Validation/Error messages
<div ngif="!contactForm.controls.firstname?.valid && (contactForm.controls.firstname?.dirty
||contactForm.controls.firstname?.touched)">
First Name is not valid
</div>
Another option is to define a getter function in the component class for each FormControl instance.
get firstname() {
return this.contactForm.get('firstname');
}
and then use it as follows in the template
<div ngif="!firstname.valid && (firstname.dirty ||firstname.touched)">
First Name is not valid
</div>
Dirty & touched
Error message
<div ngif="!firstname?.valid && (firstname?.dirty ||firstname?.touched)">
<div firstname.errors.required="" hidden="">
First Name is required
</div>
<div firstname.errors.minlength="" hidden="">
Min Length is 10
</div>
</div>
The following code is complete code of the app.component.ts file
import { Component, ViewChild, ElementRef } from '@angular/core';
import { FormGroup, FormControl, Validators } from '@angular/forms'
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
title = 'Angular Reactive forms';
contactForm = new FormGroup({
firstname: new FormControl('',[Validators.required,Validators.minLength(10)]),
lastname: new FormControl('',[Validators.required, Validators.maxLength(15), Validators.pattern("^[a-zA-Z]+$")]),
email:new FormControl('',[Validators.email,Validators.required]),
gender: new FormControl('',[Validators.required]),
isMarried: new FormControl('',[Validators.required]),
country: new FormControl('',[Validators.required]),
address:new FormGroup({
city: new FormControl('',[Validators.required]),
street: new FormControl('',[Validators.required]),
pincode:new FormControl('',[Validators.required])
})
})
get firstname() {
return this.contactForm.get('firstname');
}
get lastname() {
return this.contactForm.get('lastname');
}
get email() {
return this.contactForm.get('email');
}
get gender() {
return this.contactForm.get('gender');
}
get isMarried() {
return this.contactForm.get('isMarried');
}
get country() {
return this.contactForm.get('country');
}
get city() {
return this.contactForm.get("address").get('city');
}
get street() {
return this.contactForm.get("address").get('street');
}
get pincode() {
return this.contactForm.get("address").get('pincode');
}
countryList: country[] = [
new country("1", "India"),
new country('2', 'USA'),
new country('3', 'England')
];
onSubmit() {
console.log(this.contactForm.value);
}
}
export class contact {
firstname:string;
lastname:string;
gender:string;
isMarried:boolean;
country:string;
address: {
city:string;
street:string;
pincode:string;
}
}
export class country {
id: string;
name: string;
constructor(id: string, name: string) {
this.id = id;
this.name = name;
}
}
The following code is complete code of the app.component.html file
<form [formGroup]="contactForm" (ngSubmit)="onSubmit()" novalidate>
<p>
<label>First Name </label>
<input formcontrolname="firstname" id="firstname" name="firstname" type="text" />
</p>
<div ngif="!firstname?.valid && (firstname?.dirty ||firstname?.touched)">
<div firstname.errors.required="" hidden="">
First Name is required
</div>
<div firstname.errors.minlength="" hidden="">
Min Length is 10
</div>
</div>
<p>
<label>Last Name </label>
<input formcontrolname="lastname" id="lastname" name="lastname" type="text" />
</p>
<div ngif="!lastname.valid && (lastname.dirty ||lastname.touched)">
<div hidden="" lastname.errors.pattern="">
Only characters are allowed
</div>
<div hidden="" lastname.errors.maxlength="">
Max length allowed is {{lastname.errors.maxlength?.requiredLength}}
</div>
<div hidden="" lastname.errors.required="">
Last Name is required
</div>
</div>
<p>
<label>Email </label>
<input formcontrolname="email" id="email" name="email" type="text" />
</p>
<div ngif="!email.valid && (email.dirty ||email.touched)">
<div email.errors.required="" hidden="">
email is required
</div>
<div email.errors.email="" hidden="">
invalid email id
</div>
</div>
<p>
<label>Geneder </label>
<input formcontrolname="gender" id="gender" name="gender" type="radio" value="male" /> Male
<input formcontrolname="gender" id="gender" name="gender" type="radio" value="female" /> Female
</p>
<div ngif="!gender.valid && (gender.dirty ||gender.touched)">
<div gender.errors.required="" hidden="">
gender is required
</div>
</div>
<p>
<label>Married </label>
<input formcontrolname="isMarried" id="isMarried" name="isMarried" type="checkbox" />
</p>
<div ngif="!isMarried.valid && (isMarried.dirty ||isMarried.touched)">
<div hidden="" ismarried.errors.required="">
isMarried is required
</div>
</div>
<p>
<label>country </label>
<select formcontrolname="country" id="country" name="country">
<option c.id="" ngfor="let c of countryList" ngvalue="">
{{c.name}}
</option>
</select>
</p>
<div ngif="!country.valid && (country.dirty ||country.touched)">
<div country.errors.required="" hidden="">
country is required
</div>
</div>
<div formgroupname="address">
<div class="form-group">
<label>City</label>
<input class="form-control" formcontrolname="city" name="city" type="text" />
</div>
<div ngif="!city.valid && (city.dirty ||city.touched)">
<div city.errors.required="" hidden="">
city is required
</div>
</div>
<div class="form-group">
<label>Street</label>
<input class="form-control" formcontrolname="street" name="street" type="text" />
</div>
<div ngif="!street.valid && (street.dirty ||street.touched)">
<div hidden="" street.errors.required="">
street is required
</div>
</div>
<div class="form-group">
<label>Pin Code</label>
<input class="form-control" formcontrolname="pincode" name="pincode" type="text" />
</div>
<div ngif="!pincode.valid && (pincode.dirty ||pincode.touched)">
<div hidden="" pincode.errors.required="">
pincode is required
</div>
</div>
</div>
<p>{{contactForm.valid}} </p>
<p>
<button contactform.valid="" disabled="" type="submit">Submit</button>
</p>
</form>