FormControl, FormGroup and FormBuilder in Angular Reactive Form

In one of the earlier blog, I wrote about Template Driven Forms and Reactive Forms. In this blog, we will see about Reactive form in details.

What is Reactive form in Angular?

In Reactive Form, most of the code resides in class file and not in HTML template file. This is a good practice to use Reactive forms in complex scenarios. Reactive forms helps us to achieve custom and dynamic validation.

To use Reactive form within your Angular project, import ReactiveFormsModule in app.module.ts file.

import {FormsModule, ReactiveFormsModule} from '@angular/forms';
  imports: [
    BrowserModule,
    AppRoutingModule,
    FormsModule,
    ReactiveFormsModule
  ],

FormGroup and FormControl in Angular

ReactiveFormsModule provides a set of classes and directives which helps us to achieve many features to build Reactive forms, FormGroup and FormControl are one of them

  • FormControl: All input fields defined in HTML template are the instance of FormControl.
  • FormGroup: It is an instance of a set of FormControl is referred as FormGroup
Below is the template code to create a basic input form. Note that, I have used formControlName for each field below. 

    <h1>Add New Products</h1>
    <form [formGroup]="addProductForm">
        <div class="form-group">
            <label>Product Name</label>
            <input type="text" class="form-control" formControlName="productName">
        </div>
        <div class="form-group">
            <select class="custom-select" formControlName="productCategory">
                <option selected>Select Category</option>
                <option *ngFor="let item of prodCategory">{{item}}</option>
            </select>
        </div>
        <div class="form-group">
            <label>Product Details</label>
            <input type="text" class="form-control" formControlName="productDetails">
        </div>
        <div class="form-group">
            <label>Product Cost</label>
            <input type="text" class="form-control" formControlName="productCost">
        </div>
    </form>

Import FormGroup and ReactiveFormsModule in module file.

import {FormsModule, ReactiveFormsModule} from '@angular/forms';
 imports: [
    BrowserModule,
    AppRoutingModule,
    FormsModule,
    ReactiveFormsModule

Now, import FormGroup and FormControl in component class file.

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

@Component({
  selector: 'app-add-products',
  templateUrl: './add-products.component.html',
  styleUrls: ['./add-products.component.css']
})
export class AddProductsComponent implements OnInit {

  addProductForm = new FormGroup(
    {
      productName: new FormControl(''),
      productCategory: new FormControl(''),
      productDetails: new FormControl(''),
      productCost: new FormControl('')
    }
  );

  constructor() { }

  ngOnInit() {
  }

}

You may notice that each field is treated as the instance of a FormControl and overall instance is FormGroup

  addProductForm = new FormGroup(
    {
      productName: new FormControl(''),
      productCategory: new FormControl(''),
      productDetails: new FormControl(''),
      productCost: new FormControl('')
    }
  );

SetValue and PatchValue

  • SetValue: It accepts an object that matches the structure of the FormGroup with control names as key.
  • PatchValue: It accepts an object and does its best to match the values. It can accepts partial form group structure. Partial means, not all control data is available to bind only few control data is available.

SetValue

In setValue() we need all control data to match the structure and then will bind the data to the form.

  ngOnInit() {
    this.bindData();
  }

  bindData()
  {
    this.addProductForm.setValue(
      {
        productName:'Product1', 
        productCategory :'Electronics',
        productDetails : 'New model',
        productCost: 10000
      }
    );
  }

PatchValue

In patchValue() we may not require all control data to bind the data to the form.

  ngOnInit() {
    this.bindData();
  }

  bindData()
  {
    this.addProductForm.patchValue(
      {
        productName:'Product1', 
        productCost: 10000
      }
    );
  }

FormBuilder Service in Angular

We have seen that all controls available in HTML template file are instance of FormControl defined in component class file. But,initializing 20 or 25 controls with FormControl instances is too boring as it is a repetitive task.

To avoid this repetitive task, Angular provides FormBuilder service to handle controls. group() method in FormBuilder takes an object with control names as key.

To use FormBuilder in Angular project, first import FormBuilder from angular/forms as shown in below code snippet.

Next use group method which takes the control name as a key.

import { FormBuilder } from '@angular/forms';
  addProductForm = this.formBuildr.group(
    {
      productName: [],
      productCategory: [],
      productDetails: [],
      productCost: []
    }
  );
Hope you like this blog on Angular Reactive Forms approach which describes about FormControl, FormGroup and Form Builder.

Comments