What Is Form Validation?
Form validation is a process to check where the information provided by the user is met our requirements or not.That is provided data is in right format or not. Before Submitting to the server,it is important to ensure all required form fields are filled out in correct format.This article leads you through reactive form fields concepts and examples of form validation in Angular.
Template Driven Vs Reactive Forms.
In Angular we have two options to create a form, first one is Template driven form and second one is Reactive Form. These two comes in
@angular/form library and have many control classes. Template-driven forms make use of the “FormsModule“, while reactive forms are based on “ReactiveFormsModule“.Template-driven forms are asynchronous in nature, whereas Reactive forms are mostly synchronous.Template driven form is Suitable for simple scenarios where as Reactive Form Handles any complex scenarios.
Introduction.
Angular is a full-fledged framework, has provided excellent support for validating user inputs and displaying validation messages. It has lots of commonly used built-in validators that we can take advantage of, or we can even write our custom validators. In this post, we will learn about validations in reactive forms in Angular. We will create a simple user registration form and implement some inbuilt validations on it. Along with the inbuilt validations, we will also implement some custom validations to the reactive form.
We will perform the following custom validations for this registration form.
- Name should be in character and space only.
- Email id should be in proper format.
- Mobile no should be number only.
- Password and Confirm Password should be matched.
Create the Angular app.
ng new angular-form-validation
Change directories to the newly created project and open the project in VS Code using the set of command shown below.
cd angular-forms-validation code.
Generate Registration component.
ng g c registration
Update app-routing.module.ts file.
Update app-routing.module.ts file to create route for registration component.
import { NgModule } from '@angular/core'; import { Routes, RouterModule } from '@angular/router'; import { RegistrationComponent } from './login.component'; const routes: Routes = [ { path: 'register', component: RegistrationComponent } ]; @NgModule({ imports: [RouterModule.forRoot(routes)], exports: [RouterModule] }) export class AppRoutingModule { }
Add Below code in registration.component.html.
<div class="container"> <div class="row"> <div class="col-md-12 "> <h3>Reactive Form Validation In Angular.</h3> <form [formGroup]="registerForm" (ngSubmit)="onSubmit()"> <div class="row"> <div class="col"> <label>First Name</label> <input type="text" formControlName="firstName" class="form-control" [ngClass]="{ 'is-invalid': submitted && f.firstName.errors }" [ngClass]="{ 'is-valid': !f.firstName.errors }" /> <div *ngIf="submitted && registerForm.controls.firstName.errors" class="invalid-feedback"> <div *ngIf="f.firstName.errors?.required">First Name is required</div> <div *ngIf="f.firstName.errors?.pattern">First Name not valid.</div> </div>
<div class="text-danger" *ngIf="f.firstName.touched && f.firstName.errors?.required">
First Name is required
</div> </div> <div class="col"> <label>Last Name</label> <input type="text" formControlName="lastName" class="form-control" [ngClass]="{ 'is-invalid': submitted && f.lastName.errors }" /> <div *ngIf="submitted && f.lastName.errors" class="invalid-feedback"> <div *ngIf="f.lastName.errors?.required">Last Name is required</div> <div *ngIf="f.lastName.errors?.pattern">Last Name not valid.</div> </div>
<div class="text-danger"
*ngIf="f.lastName.touched && f.lastName.errors?.required">
Last Name is required
</div> </div> </div> <div class="row"> <div class="col"> <label>Email</label> <input type="text" formControlName="email" class="form-control" [ngClass]="{ 'is-invalid': submitted && f.email.errors }" /> <div *ngIf="submitted && f.email?.errors" class="invalid-feedback"> <div *ngIf="f.email.errors?.required">Email is required</div> </div>
<div class="text-danger" *ngIf="f.email.touched && f.firstName.errors?.required">
Name is required
</div> </div> <div class="col"> <label>Mobile Number </label> <input type="text" formControlName="mobileno" class="form-control" [ngClass]="{ 'is-invalid': submitted && f.mobileno.errors }" /> <div *ngIf="submitted && f.mobileno.errors" class="invalid-feedback"> <div *ngIf="f.mobileno.errors?.required">Mobile no is required</div> <div *ngIf="f.mobileno.errors?.pattern">Invalid Mobile No.</div> </div>
<div class="text-danger" *ngIf="f.mobileno.touched && f.mobileno.errors?.required">
Mobile no is required
</div> </div> </div> <div class="row"> <div class="col"> <label>Gender </label> <input type="radio" formControlName="gender" value= "male" [ngClass]="{ 'is-invalid': submitted && f.gender.errors }"/>Male <input type="radio" formControlName="gender" value="female" [ngClass]="{ 'is-invalid': submitted && f.gender.errors }"/>FeMalem <div *ngIf="submitted && f.gender.errors" class="invalid-feedback"> <div *ngIf="f.gender.errors?.required">Gender is required</div> </div>
<div class="text-danger" *ngIf="f.gender.touched && f.gender.errors?.required">
Gender is required
</div> </div> <div class="col"> <label>Hobbies </label> <input type="checkbox" formControlName="hobbies" value="playing" [ngClass]="{ 'is-invalid': submitted && f.hobbies.errors }" />Playing <input type="checkbox" formControlName="hobbies" value="singing" [ngClass]="{ 'is-invalid': submitted && f.hobbies.errors }" />Singigng<br> <input type="checkbox" formControlName="hobbies" value="Dancing" [ngClass]="{ 'is-invalid': submitted && f.hobbies.errors }" />Dancing <div *ngIf="submitted && f.hobbies.errors" class="invalid-feedback"> <div *ngIf="f.hobbies.errors?.required">Hobbies is required</div> </div> </div> </div> <div class="row"> <div class="col"> <label>Password</label> <input type="password" formControlName="password" class="form-control" [ngClass]="{ 'is-invalid': submitted && f.password.errors }" /> <div *ngIf="submitted && f.password.errors" class="invalid-feedback"> <div *ngIf="f.password.errors?.required">Password is required</div> <div *ngIf="f.password.errors?.minlength">Password must be at least 6 characters</div> </div> </div> <div class="col"> <label>Confirm Password</label> <input type="password" formControlName="confirmPassword" class="form-control" [ngClass]="{ 'is-invalid': submitted && f.confirmPassword.errors }" /> <div *ngIf="submitted && f.confirmPassword.errors" class="invalid-feedback"> <div *ngIf="f.confirmPassword.errors?.required">Confirm Password is required</div> <div *ngIf="f.confirmPassword.errors?.minlength">Confirm Password must be at least 6 characters</div> <div *ngIf="f.confirmPassword.errors?.confirmedValidator">Passwords must match</div> </div> </div> </div> <div class="row"> <div class="col"> <label>Date of birth</label> <input type="text" placeholder="Datepicker" class="form-control" bsDatepicker [ngClass]="{ 'is-invalid': submitted && f.dob.errors }" formControlName="dob" > <div *ngIf="submitted && f.dob.errors" class="invalid-feedback"> <div *ngIf="f.dob.errors?.required">Date of birth is required</div> </div> </div> <div class="col"> <label>Select Image</label> <input type="file" [ngClass]="{ 'is-invalid': submitted && f.dob.errors }"> <div *ngIf="f.image.errors" class="invalid-feedback"> <div *ngIf="f.image.errors?.required">Image is required</div> </div> </div> </div> <br> <div class="row"> <div class="col"> <button class="btn btn-primary">Register</button> </div> </div> </form> </div> </div> </div>
Add below code on registration.component.ts.
import { Component, OnInit } from '@angular/core'; import { FormControl,FormGroup,Validators,FormBuilder } from '@angular/forms'; import { ConfirmedValidator } from '../../helpers/confirmed.validator'; import { Router } from "@angular/router"; @Component({ selector: 'app-registration', templateUrl: './registration.component.html', styleUrls: ['./registration.component.css'] }) export class RegistrationComponent implements OnInit { registerForm!: FormGroup; submitted = false; private readonly name_pattern = '^[a-zA-Z]+$'; private readonly email_pattern = "^[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,4}$"; private readonly mobile_pattern = "^[6-9][0-9]{9}$"; constructor(private formBuilder: FormBuilder,private router: Router) { } ngOnInit() { this.registerForm = this.formBuilder.group({ firstName: ['', [Validators.required,Validators.pattern(this.name_pattern)]], lastName: ['', [Validators.required,Validators.pattern(this.name_pattern)]], email: ['', [Validators.required, Validators.email]], mobileno: ['', [Validators.required,Validators.pattern(this.mobile_pattern)]], password: ['', [Validators.required, Validators.minLength(6)]], confirmPassword: ['', [Validators.required,Validators.minLength(6)]], gender:['',[Validators.required]], hobbies:[false, Validators.requiredTrue], dob:['',Validators.required], image:['',''] }, { validator: ConfirmedValidator('password', 'confirmPassword') } ); } get f() { return this.registerForm.controls; } submitted_data:any=[] onSubmit() { this.submitted = true; // stop here if form is invalid if (this.registerForm.invalid) { return; } console.log('SUCCESS!! :-)\n\n' + JSON.stringify(this.registerForm.value)) } }
In the above component we define the form fields and validators for our registration form using an Angular FormBuilder to create an instance of a FormGroup that is stored in the registerForm property. Getter f is a convenience property to make it easier to access form controls from the template.
Create Confirmed Validator .
In this step we will create confirmed validator to check whether the password and confirm password is same or not in helpers folder. So add below code in confirmed.validator file.
import { FormGroup } from '@angular/forms'; // custom validator to check that two fields match export function ConfirmedValidator(controlName: string, matchingControlName: string){ return (formGroup: FormGroup) => { const control = formGroup.controls[controlName]; const matchingControl = formGroup.controls[matchingControlName]; if (matchingControl.errors && !matchingControl.errors.confirmedValidator) { return; } if (control.value !== matchingControl.value) { matchingControl.setErrors({ confirmedValidator: true }); } else { matchingControl.setErrors(null); } } }