Build Angular 7 Nested Form using FormArray API with Reactive Forms

Article By Rawat Digamber on

Sometimes a user needs the additional form fields to insert the dynamic data. Angular 7’s FormArray API allows creating nested form fields.In this tutorial, we will learn about how to build the nested forms using Angular 7 FormArray API with Reactive Forms. If you are new to Reactive Forms, please refer to Full Angular 7 Reactive Forms & Form Validation Tutorial.

1. Understand Nested Forms in Angular

Let’s assume if a user requires to add an item using the form. In this kind of condition, you have to create a form which allows a user to add dynamic form fields to add additional data.

2. Setting Up Reactive Form

Importing ReactiveFormsModule API

To work with Reactive Forms in Angular, please import ReactiveFormsModule service in app.module.ts file.

import { ReactiveFormsModule } from '@angular/forms';

@NgModule({
  imports: [
    ReactiveFormsModule
  ],
})

export class AppModule { }

Understand Basic Reactive Forms Services

Reactive forms are used to manage complex data entered by the user in the form. Let’s focus on some of the useful services of Reactive Forms.

  • AbstractControl: This is the main class for controlling the behavior and properties of, FormGroup, FormControl, and FormArray.
  • FormBuilder: It provides helpful methods to create control instances in Angular 7 Reactive Forms.
  • FormGroup: FormGroup is a top-level API which maintains the values, properties and validation state of a group of AbstractControl instance in Angular 7.
  • FormControl: It communicates with an HTML Form element like input or select tag, this api handles the individual form value and validation state.
  • FormArray: FormArray API maintains the values, properties and validation state of an array of the AbstractControl instances.
  • ngSubmit: This event is called when the form is submitted.

Setting Up Reactive Form in Angular Component HTML Template

app.component.html

<!-- Form starts -->
<form [formGroup]="registrationForm" (ngSubmit)="onSubmit()">
   <button type="submit" class="btn btn-danger btn-lg btn-block">Submit Form</button>
</form><!-- Form ends -->

Setting Up Reactive Form

app.component.ts

import { Component } from '@angular/core';
import { FormBuilder, FormArray } from "@angular/forms";

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

export class AppComponent {
  
  constructor(public fb: FormBuilder) {}

  /*############ Registration Form ############*/
  registrationForm = this.fb.group({
    addDynamicElement: this.fb.array([])
  })

  // Submit Registration Form
  onSubmit() {
    alert(JSON.stringify(this.registrationForm.value))
  }

}

3. Setting Up Nested Form Layout Using HTML & FormArrayName Directive

Let’s set up the HTML layout for creating Nested forms group in Angular. I will be using following directives to work with nested forms in Angular.

  • formArrayName: It syncs a nested FormArray to a DOM element.
  • *ngFor: It’s a structural directive provided by Angular that loops over every item in a collection.
<!-- Form starts -->
<form [formGroup]="registrationForm" (ngSubmit)="onSubmit()">
   <!-- Add nested items dynamically-->
   <div class="group-gap" formArrayName="addDynamicElement">
      <h5 class="mb-3">Add Products</h5>
      
       <div class="mb-3">
         <button type="button" class="btn btn-sm btn-success mb-3 btn-block" (click)="addSuperPowers()">Add Items</button>
         <ul class="subjectList">
            <li *ngFor="let item of addDynamicElement.controls; let i = index">
               <input type="text" class="form-control" [formControlName]="i">
            </li>
         </ul>
      </div>

      <button type="submit" class="btn btn-danger btn-lg btn-block">Submit Form</button>
   </div>
</form><!-- Form ends -->

Understand Dynamic Forms Array

I will delcate a JavaScript getter method to access the addDynamicElement form control. Then i will assign FormArray to form control, it will make it an array. Once i am done with this process, then i will addItems() function and push the dynamically created form control into the addDynamicElement array.

/*############### Add Dynamic Elements ###############*/
get addDynamicElement() {
  return this.registrationForm.get('addDynamicElement') as FormArray
}

addItems() {
  this.addDynamicElement.push(this.fb.control(''))
}

Let’s checkout the output.

app.component.ts

import { Component } from '@angular/core';
import { FormBuilder, FormArray, Validators } from "@angular/forms";

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

export class AppComponent {
  
  constructor(public fb: FormBuilder) {}

  /*################ Registration Form ################*/
  registrationForm = this.fb.group({
    addDynamicElement: this.fb.array([])
  })

  /*############### Add Dynamic Elements ###############*/
  get addDynamicElement() {
    return this.registrationForm.get('addDynamicElement') as FormArray
  }

  addItems() {
    this.addDynamicElement.push(this.fb.control(''))
  }

  // Submit Registration Form
  onSubmit() {
    alert(JSON.stringify(this.registrationForm.value))
  }

}

Angular Nested Form Demo

We’ve created nested form with Angular, we have used reactive forms to manage nested data required by the user. Let’s check out below how does it work?

Feel free to contact me, If you are looking for a freelance web and mobile app developer in India, with the following skills: Angular JS, Angular 2+, Node JS, Firebase, MongoDB, Ionic Framework and WordPress.

I also offer remote contracting services to clients across the globe.

Get Started