Menu Close

Reactive Forms in Angular

In this lesson we will learn about Reactive Forms in Angular. Reactive forms ( also known as Model-driven forms) are one of the two ways to build Angular forms. Please read my previous lesson of Template driven forms in Angular.

To build reactive forms, first, we need to import ReactiveFormsModule. We then create the Form Model in component class using Form GroupForm Control & FormArrays. Next, we will create the HTML form template and bind it to the Form Model.

What are Reactive Forms?

Reactive forms are forms where we define the structure of the form in the component class. i.e. we create the form model with Form GroupsForm Controls, and FormArrays. We also define the validation rules in the component class. Then, we bind it to the HTML form in the template.

Reactive Forms Example

Let’s first create a sample Angular application using command ng new reactive-forms. Here “reactive-forms” is our project name. We set Routing as Yes and

Import ReactiveFormsModule

To work with Reactive forms, we must import the ReactiveFormsModule. We usually import it in root module or in a shared module. The ReactiveFormsModule contains all the form directives and constructs for working with angular reactive forms.

import { NgModule } from '@angular/core';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { BrowserModule } from '@angular/platform-browser';

import { AppComponent } from './app.component';
import { ReactiveFormComponent } from './components/reactive-form/reactive-form.component';
import { TemplateDrivenComponent } from './components/template-driven/template-driven.component';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { MatCardModule } from "@angular/material/card";
import { MatButtonModule } from "@angular/material/button";
@NgModule({
  declarations: [
    AppComponent,
    ReactiveFormComponent,
    TemplateDrivenComponent
  ],
  imports: [
    BrowserModule,
    FormsModule,
    ReactiveFormsModule,
    BrowserAnimationsModule,
    MatCardModule, 
    MatButtonModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

Creating the Form Model

In the Reactive Forms approach, it is our responsibility to build model using FormGroup, FormControl & FormArray.

The FormGroupFormControl & FormArray are the three building blocks of the Angular Forms. We learned about them in the Angular Forms Tutorial. FormControl encapsulates the state of a single form element in our form. It stores the value and state of the form element and helps us to interact with them using properties & methods.

FormGroup represents a collection of form controls. It can also contain other FormGroups and FormArrays. In fact, an angular form is a FormGroup.

The FormGroup is created with the following syntax

contactForm = new FormGroup({})

The FormGroup takes 3 arguments. a collection of a child controls (which can be FormControl, FormArray, or another FormGroup), a validator, and an asynchronous validator. The validators are optional.

Adding the Child Controls

The next step is to add the child controls to the contactForm. The first argument to FormGroup is the collection of controls. The Controls can be FormControlFormArray or another FormGroup. It can be done by creating a new instance for FormControl (or FormGroup or FormArray).

contactForm = new FormGroup({
  firstname: new FormControl(),
  lastname: new FormControl(),
  email: new FormControl(),
  gender: new FormControl(),
  isMarried: new FormControl(),
  country: new FormControl()
})

HTML Form

The next task is to build an HTML form, We enclose it in a <form> tag. We have included two text inputs (FirstName & LastName), an email field, a radio button (gender), a checkbox (isMarried), and a select list (country). These are simple HTML Form elements.

<form>
  <p>
    <label for="firstname">First Name </label>
    <input type="text" id="firstname" name="firstname">
  </p>
  <p>
    <label for="lastname">Last Name </label>
    <input type="text" id="lastname" name="lastname">
  </p>
  <p>
    <label for="email">Email </label>
    <input type="text" id="email" name="email">
  </p>
  <p>
    <label for="gender">Geneder </label>
    <input type="radio" value="male" id="gender" name="gender"> Male
    <input type="radio" value="female" id="gender" name="gender"> Female
  </p>
  <p>
    <label for="isMarried">Married </label>
    <input type="checkbox" id="isMarried" name="isMarried">
  </p> 
  <p>
    <label for="country">country </label>
    <select id="country" name="country">
      <option value="1">India</option>
      <option value="2">USA</option>
      <option value="3">England</option>
      <option value="4">Singapore</option>
    </select>
  </p>
  <p>
    <button type="submit">Submit</button>
  </p>
</form>

Binding the template to the model

Now we need to associate our model with the above HTML Template. We need to tell angular that we have a model for the form.

<form [formGroup]="contactForm">

Next, we need to bind each form field to an instance of the FormControl models. We use the FormControlName directive for this. We add this directive to every form field element in our form. The value is set to the name of the corresponding FormControl instance in the component class.

<input type="text" id="firstname" name="firstname" formControlName="firstname">
<input type="text" id="lastname" name="lastname" formControlName="lastname">

Submit form

We submit the form data to the component using the Angular directive named ngSubmit.  Note that we already have a submit button in our form. The ngSubmit directive binds itself to the click event of the submit button. We are using event binding (parentheses) to bind ngSubmit to OnSubmit method. When the user clicks on the submit button ngSubmit invokes the OnSubmit method on the Component class.

<form [formGroup]="contactForm" (ngSubmit)="onSubmit()">

Final HTML template look like below,

<form [formGroup]="contactForm" (ngSubmit)="onSubmit()">
  <p>
    <label for="firstname">First Name </label>
    <input type="text" id="firstname" name="firstname" formControlName="firstname">
  </p>
  <p>
    <label for="lastname">Last Name </label>
    <input type="text" id="lastname" name="lastname" formControlName="lastname">
  </p>
  <p>
    <label for="email">Email </label>
    <input type="text" id="email" name="email" formControlName="email">
  </p>
  <p>
    <label for="gender">Geneder </label>
    <input type="radio" value="male" id="gender" name="gender" formControlName="gender"> Male
    <input type="radio" value="female" id="gender" name="gender" formControlName="gender"> Female
  </p>
  <p>
    <label for="isMarried">Married </label>
    <input type="checkbox" id="isMarried" name="isMarried" formControlName="isMarried">
  </p>
  <p>
    <label for="country">country </label>
    <select id="country" name="country" formControlName="country">
      <option value="1">India</option>
      <option value="2">USA</option>
      <option value="3">England</option>
      <option value="4">Singapore</option>
    </select>
  </p>
  <p>
    <button type="submit">Submit</button>
  </p>
</form>

Receive the data in the Component class

The last step is to receive the form data in the component class. All we need to do is to create the onSubmit method in our component class.

onSubmit() {
  console.log(this.contactForm.value);
}

We are using the console.log(this.contactForm.value) to send the value of our form data to the console window.

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

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

  myreactiveForm!: FormGroup;

  contactForm = new FormGroup({
    firstname: new FormControl(),
    lastname: new FormControl(),
    email: new FormControl(),
    gender: new FormControl(),
    isMarried: new FormControl(),
    country: new FormControl()
  });
  
  ngOnInit(): void {
    // create an instance of form group
    // for the object passed, the key identifies the control name, the value identifies the actual control
    // the Validators provides validator functions that need to be applied to the control value
    this.myreactiveForm = new FormGroup({
      'name': new FormControl('', [Validators.required]),
      'emailAddress': new FormControl('', [Validators.required, Validators.email]),
      'age': new FormControl('', [Validators.required, Validators.pattern('^[0-9]+$')])
    });
  }
  onSubmit() {
    console.log(this.myreactiveForm.value);
  }
}

FormControl

FormControl takes 3 arguments. a default value, a validator, and an asynchronous validator. All of them are optional.

Default Value

You can pass a default value either as a string or as an object of key-value pair. When you pass an object you can set both the value and the whether or not the control is disabled.

//Setting Default value as string
firstname= new FormControl('John');

//Setting Default value & disabled state as object
firstname: new FormControl({value: 'John', disabled: true}),

Sync Validator

The second parameter is an array of sync Validators. Angular has some built-in Validators such as required and minLength etc.

firstname: new FormControl('', [Validators.required,Validators.minLength(10)]),

Asynchronous validator

The third argument is the Async Validator. The syntax of Async Validators is similar to Sync Validators.

Grouping the controls using FormGroup

We can group various FormControls together. For Example fields such as street, city, country and Pincode each will have their own FormControl but can be grouped together as an address FormGroup.

contactForm = new FormGroup({
  firstname: new FormControl(),
  lastname: new FormControl(),
  email: new FormControl(),
  gender: new FormControl(),
  isMarried: new FormControl(),
  address:new FormGroup({
    city: new FormControl(),
    street: new FormControl(),
    pincode:new FormControl(),
    country: new FormControl(),
  })
})

Conclusion

In this lesson we will learn about Reactive Forms in Angular. Reactive forms ( also known as Model-driven forms) are one of the two ways to build Angular forms.

Leave behind your valuable queries and suggestions in the comment section below. Also, if you think this article helps you, do not forget to share this with your developer community. Happy Coding 🙂

Jayant Tripathy
Coder, Blogger, YouTuber

A passionate developer keep focus on learning and working on new technology.

Leave a Reply

Your email address will not be published.