How to use angular reactive form validation – example

In previous we have learned, the template drives forms, in a template-driven from where most of our logic, validation, controls are in template or HTML form. We are applying ngModel and other an Angular directive in template and template drive form is suitable for building the simple form with basic validation(required, minlength, maxlength). In these articles, we will learn details on angular reactive form validation,

What is a angular reactive form ?

Reactive form, all the control and logic validation of form are configured and defined in the component typescript file. We do not configure form in the template, we are only synchronizing it with the directives, formControlName and formGroup. This approach, we create a form from the instance of FormGroup. The FormGroup instance allows us to specify form controls and the various validations on the input element of the form. The reactive form is the best choice for creating a complex form, it provides the developer with more control on the form.

Example on Angular reactive form validation.

We will demonstrate reactive form example, we have to follow these step to complete our task.

Step 1: Import reactive form module in app.module.ts file

We need to import reactive form module and this module containing all the tools we need now to build our own form.
import { ReactiveFormsModule } from '@angular/forms';

imports: [
   ReactiveFormsModule
],

Step 2:Initialize reactive form and add validation for Angular reactive form validation.

The reactive form we should initialize it before rendering the template so define form setup in ngOnInit() method.
The FormGroup contains FromControls (rendered as key/value pairs) which are used to target each individual input field in our form. The formControls first argument is the default value of the control element and the second argument is validator can be a single or an array of validators we want to apply to this control element. The third argument will be potential asynchronous validators. Each FormControl is assigned its respective Validators, we can also assign our custom validation methods from our own custom Validator service.
import { Component, OnInit } from '@angular/core';
import { FormGroup, FormBuilder, Validators } from '@angular/forms';
import { TamoDepartment } from './model/department.interface';
import { MockDepartment } from './data/mockDepartment';

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

export class AppComponent implements OnInit{
  public title: string  = 'Angular Reactive Form';
  public formTamo : FormGroup;

  departments: any[];
  titleErrorMessage: string;
  descriptionErrorMessage : string;
  categoryErrorMessage: string;

  constructor(private formBuilder: FormBuilder){
    this.displayDepartments();
  }

  ngOnInit(){
    this.formTamo = this.formBuilder.group({
      "title": [null, Validators.required],
      "description": [null, [Validators.required, Validators.minLength(10), Validators.maxLength(50)]],
      "category" : [null]
    })
  }

  displayDepartments(){
    this.departments = MockDepartment;
    this.initializeErrorMessages();
  }
  
  initializeErrorMessages(){
    this.titleErrorMessage = "This is required";
    this.descriptionErrorMessage ="Description should be of minimum 10 and maximun 50 characters";
    this.categoryErrorMessage = "Category is required";
  }
}

We have to import formGroup and formbuilder from @angular/forms in our component.
Form Group
A FormGroup aggregates the values of each child FormControl into one object, with each control name as the key. It calculates its status by reducing the statuses of its children. For example, if one of the controls in a group is invalid, as a result, the entire group becomes invalid. The FormGroup is useful as a way to group relevant form fields under one group. This gives us the convenience of whether we want to track the form controls individually, or as a group.

FormBuilder
Angular has a helper Class called FormBuilder. FormBuilder allows us to explicitly declare forms in our components. This allows us to also explicitly list each form control’s validators. FormBuilder has methods as group(), control() and array() that returns FormGroup, FormControl and FormArray respectively. Using FormBuilder we can directly pass the object or array of objects of a class to create the form.

In reactive form allow us group elements into a group and we will group both name and email fields into a FormGroup called Student.

Displaying custom error message for form element in the template:

The FormArray class is a way to manage the collection of Form controls in Angular. The controls can be a FormGroup, a FormControl, or another FormArray. Access the FormArray control, we can access form control two way in component template.
1. First by using get() method we can easily access the form array instance. as
 <span *ngIf="!form.get('email').valid && signupForm.get('email').touched">Please enter a valid email!</span>

2. Using form control as we did in our example to check form element validation.
Displaying a custom error message for each form element error related to validation. We will define the form model on from an instance of FormGroup and we will use form validation from FormBuilder instance. We have to import FormGroup and FormBuilder provider from ‘@angular/form’. 

The Built-in Angular Validation Attributes for angular reactive form validation.

required: This attribute is used to specify a value that must be provided.
minlength: This attribute is used to specify a minimum number of characters.
maxlength: This attribute is used to specify a maximum number of characters. This type of validation cannot be applied directly to form elements because it conflicts with the HTML5 the attribute of the same name. It can be used with model-based forms.
pattern: This attribute is used to specify a regular expression that the value provided by the user must match.

We can assign the value of the form select element department option value from the external data in file app/data /mockDepartment.ts

app/model/department.interface.ts

export interface TamoDepartment{
    id:number,
    name: string,
    description: string
}

In app/data/mockDepartment.ts we have to define the list of department name to array element TamoDepartment[]

import { TamoDepartment } from '../model/department.interface';

export const MockDepartment : TamoDepartment[] = [
    {
        id: 0,
        name: 'Designing',
        description: 'Photoshop, Indesign'
    },
    {
        id: 1,
        name: 'Web Developer',
        description: 'Web through Node and Angular'
    },
    {
        id: 3,
        name: 'Hybrid App Developer',
        description: 'Through Ionic'
    },
    {
        id: 3,
        name: 'Android Developer',
        description: 'The 140 Android App developed'
    },   
    {
        id: 4,
        name: 'IOS Developer',
        description: 'Lastest ISO'
    }
]

Step 3:Add required form directives for reactive form.

We need the following form directives to overwrite default behavior of form by instructing Angular to synchronous form in the template with form in typescript.
1. formGroup : This directive tells an Angular not to create form and use our signUpForm which we have created in typescript. We have to assign a form name (formTamo) to an Angular directive [fromGroup]. This directive we have used as property binding and we pass our form as an argument to the directive. In our template, we have the formGroup property on our HTML form to create a link with the FormBuilder logic in the component class and the template input fields.
2. formControlName: Each input field has a formControl assigned to it whose value is mapped to the specified FormControl object in the component class. This relationship allows the FormGroup helper to retrieve each field’s input value.
ngSubmit: The ngSubmit binding handles the form submits an event.
<div class="container">
  <h1> {{title}} </h1>
  <div class="card">  
    <div class="card-block">
      <form [formGroup]="formTamo" (ngSubmit)="submitDetails(formTamo.value)">
        <div class="form-group">
          <label>Title :</label> 
          <input type="text" class="form-control" formControlName="title" />
          <div class="alert alert-danger" *ngIf="!formTamo.controls['title'].valid && formTamo.controls['title'].touched" >
            {{ titleErrorMessage }}
          </div>
        </div>

        <div class="form-group">
          <label>Description :</label> 
          <textarea class="form-control" formControlName="description"></textarea>
          <div class="alert alert-danger" 
            *ngIf="!formTamo.controls['description'].valid && formTamo.controls['description'].touched" >
              {{ descriptionErrorMessage  }}
            </div>
        </div>

        <div class="form-group">
          <label>Department :</label> 
          <select class="form-control" formControlName="category">
            <option *ngFor ="let item of categories" value="{{item.name}}">{{item.name}}</option>
          </select>
        </div>
        <button class="btn btn-primary btn-block">Submit</button>
      </form>
    </div>
    <p>Form Element : {{formTamo.value | json}}</p>
  </div>

</div><!-- End of container div -->
Angular reactive form validation

Styling Elements Using Validation Classes in angular reactive form validation

The underlying Angular framework detects the validation state of the input field and applies its own specific classes to reflect those states. The classes to which an input element is assigned provide details of its validation state as.

ng-dirty: Input field had interacted with.
ng-touched: Input field has received focus.
ng-valid: Data entry has passed validation.
ng-invalid: Data entry has not passed validation)
ng-pristine: An element if its contents have not been changed.

We can apply the red border on the input of invalid form element by adding the following CSS style in app.component.scss as.

input.ng-invalid.ng-touched {
  border: 1px solid red;
}

Check more information on angular reactive form validation on official documentation.

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top