Angular FormBuilder Example
August 20, 2021
This page will walk through Angular FormBuilder
example. The FormBuilder
is used to create a big reactive form with minimum code in Angular application. The FormBuilder
methods are group()
, control()
and array()
that returns FormGroup
, FormControl
and FormArray
respectively. Using FormBuilder
we can directly pass object or array of object of a class to create the form. We need to create form HTML template with formArrayName
by assigning the field name of that class.
Suppose we want to create a
FormGroup
with some fields, then first create a class with those fields and then pass the instance of that class to FormBuilder.group()
and it will return FormGroup
with form controls named as class fields. After form submit, we can get complete form value as an object of a class. In this way, with the help of FormBuilder
, we can create form using object of a class, set values in the form using object of a class and also we can fetch form values as an object of a class after form submit. Now we will provide complete FormBuilder
example step-by-step.
Contents
Technologies Used
Find the technologies being used in our example.1. Angular 12.1.0
2. Node.js 12.14.1
3. NPM 7.20.3
Project Structure
Find the project structure of our demo application.angular-demo | |--src | | | |--app | | | | | |--employee.ts | | |--department.ts | | |--team.ts | | |--team-data.ts | | |--team-management.service.ts | | |--team-management.component.ts | | |--team-management.component.html | | |--app.component.ts | | |--app.module.ts | | | |--main.ts | |--index.html | |--styles.css | |--node_modules |--package.json
FormBuilder
FormBuilder
creates reactive form with minimum code using FormGroup
, FormControl
and FormArray
. FormBuilder
has following methods.
group(): Creates
FormGroup
.
control(): Creates
FormControl
.
array(): Creates
FormArray
.
Find the sample example to create a form with
FormBuilder
.
this.teamForm = this.formBuilder.group({ teamName: ['', Validators.required ], teamManager: '', teamDept: this.formBuilder.group(new Department()), employees: this.formBuilder.array([]) });
Using FormBuilder.group()
FormBuilder.group()
constructs a new FormGroup
with the given configuration. We can pass the parameter as following.
1.
teamDept: this.formBuilder.group({ deptHead: '', deptName: '' })
Department
class with fields deptHead
and deptName
. Using FormBuilder.group()
we can create FormGroup
as following.
teamDept: this.formBuilder.group(new Department())
The HTML template for both the above example, will be same.
<div formGroupName="teamDept" class="department"> <p>Department Head : <input formControlName="deptHead"></p> <p>Department Name : <input formControlName="deptName"></p> </div>
teamDept: this.formBuilder.group({ deptHead: 'Modi', deptName: 'M Commerce' })
FormBuilder.group()
method then we need to set default values in the object.
Using FormBuilder.array()
FormBuilder.array()
constructs new FormArray
for the given configuration. We can pass configuration as an array of FormGroup
or FormControl
. We can get FormArray
using FormBuilder.array()
in following ways.
1.
employees: this.formBuilder.array([{'empId': '', 'empName': '', 'skill': ''}])
FormArray
at run time.
Create a method to get the
FormArray
instance.
get empFormArray(): FormArray{ return this.teamForm.get('employees') as FormArray; }
FormArray
at run time, FormArray
has FormArray.push()
method. Now suppose we want to add FormGroup
in the FormArray
instance, we can write code as follows.
addEmployee(){ let fg = this.formBuilder.group(new Employee()); this.empFormArray.push(fg); }
FormGroup.setControl()
to replace existing instance of FormGroup
, FormControl
or FormArray
by new one. Suppose we want to replace FormArray
instance at run time, first we will create an array of FormArray
using FormBuilder.array()
and replace existing data with new instance using FormGroup.setControl()
. Find the code snippet.
let employeeFormGroups = team.employees.map(employee => this.formBuilder.group(employee)); let employeeFormArray = this.formBuilder.array(employeeFormGroups); this.teamForm.setControl('employees', employeeFormArray);
<div formArrayName="employees"> <div *ngFor = "let emp of empFormArray.controls; let idx = index" [formGroupName]="idx" class="employee"> <p> <b>Employee : {{idx + 1}}</b> </p> <p>Emp Id : <input formControlName="empId"></p> <p>Emp Name : <input formControlName="empName"></p> <p>Skill : <select formControlName="skill"> <option *ngFor="let skill of allSkills | async" [ngValue]="skill.name"> {{ skill.displayName }} </option> </select> </p> </div> </div>
FormArray
for a given index, we can use removeAt()
method of FormArray
as following.
deleteEmployee(idx: number) { this.empFormArray.removeAt(idx); }
Set Value in Form
FormGroup
has two methods to set form values and that are setValue()
and patchValue()
. setValue()
performs strict check and throw error if there is mismatch between existing form controls and the form controls which we are setting. If we use patchValue()
then it will not throw error in case of mismatch of form controls. To set values in the form we can directly pass our object. Find the code snippet.
Using
setValue()
this.teamForm.setValue(team);
patchValue()
this.teamForm.patchValue(team);
this.teamForm.patchValue({ teamName: team.teamName, teamManager: team.teamManager, teamDept: team.teamDept });
Form Validation
To validate reactive form we need to useValidators
class that has validation methods such as required()
, email()
, minLength()
, maxLength()
etc. Find the code snippet to validate a form field.
this.teamForm = this.formBuilder.group({ teamName: ['', Validators.required ], teamManager: ['', Validators.minLength(15) ], --------------- });
<p>Team Name : <input formControlName="teamName"> <br/><label *ngIf="teamForm.get('teamName')?.invalid && teamForm.get('teamName')?.dirty" class = "error"> Team name is required. </label> </p>
Fetch Form Data After Form Submit
We can fetch form data after form submit individually as well as complete data as an object of a class. To fetch form data individually, write code as follows.let teamName = this.teamForm.get('teamName').value;
let team: Team = this.teamForm.value;
let data = JSON.stringify(this.teamForm.value);
Reset Form
To reset reactive form,FormGroup
has reset()
method. We need to call this method on the instance of FormGroup
as following.
this.teamForm.reset();
this.teamForm.reset({ teamName: 'Java Team', teamManager: 'Yogi' });
Complete Example
app.component.tsimport { Component } from '@angular/core'; @Component({ selector: 'app-root', template: ` <app-team></app-team> ` }) export class AppComponent { }
export class Employee { empId = ''; empName = ''; skill = ''; }
export class Department { deptHead = ''; deptName = ''; }
import { Employee } from './employee'; import { Department } from './department'; export class Team { teamName = ''; teamManager = ''; teamDept = {} as Department; employees = [] as Employee[]; }
import { Team } from './team'; export const ALL_TEAMS: Team[] = [ { "teamName":"Java Team", "teamManager":"Yogi", "teamDept":{ "deptHead":"Modi", "deptName":"M Commerce" }, "employees":[ { "empId":"101", "empName":"Harish", "skill":"Java" }, { "empId":"111", "empName":"Mohit", "skill":"Angular" } ] } ]; export const ALL_SKILLS = [ {name: 'Java', displayName: 'Java'}, {name: 'Angular', displayName: 'Angular'}, {name: 'Dot Net', displayName: 'Dot Net'} ];
import { Injectable } from '@angular/core'; import { Observable, of } from 'rxjs'; import { map } from 'rxjs/operators'; import { Team } from './team'; import { ALL_TEAMS, ALL_SKILLS } from './team-data'; @Injectable() export class TeamManagementService { getSkills() { return of(ALL_SKILLS); } getAllTeams(): Observable<Team[]> { return of(ALL_TEAMS); } getTeamByName(name: string): Observable<Team> { return this.getAllTeams().pipe( map(allTeams => allTeams.find(team => team.teamName === name) ?? new Team()) ); } saveTeam(team: Team) { console.log('------------TEAM------------'); console.log('Team Name: ' + team.teamName); console.log('Team Manager: ' + team.teamManager); console.log('Dept Head: ' + team.teamDept.deptHead); console.log('Dept Name: ' + team.teamDept.deptName); console.log('----- Employee Detail -----'); for (let emp of team.employees) { console.log('Emp Id: ' + emp.empId); console.log('Emp Name: ' + emp.empName); console.log('Emp Skill: ' + emp.skill); console.log('-------------------'); } } }
import { Component, OnInit } from '@angular/core'; import { FormGroup, FormArray, Validators, FormBuilder } from '@angular/forms'; import { of } from 'rxjs'; import { TeamManagementService } from './team-management.service'; import { Team } from './team'; import { Employee } from './employee'; import { Department } from './department'; @Component({ selector: 'app-team', templateUrl: './team-management.component.html' }) export class TeamManagementComponent implements OnInit { teamForm = {} as FormGroup; formSubmitted = false; allSkills = of([] as any); constructor( private formBuilder: FormBuilder, private teamMngService: TeamManagementService) { } ngOnInit() { this.allSkills = this.teamMngService.getSkills(); this.createTeamForm(); this.addEmployee(); } createTeamForm() { this.teamForm = this.formBuilder.group({ teamName: ['', Validators.required], teamManager: '', teamDept: this.formBuilder.group(new Department()), employees: this.formBuilder.array([]) }); } get empFormArray(): FormArray { return this.teamForm.get('employees') as FormArray; } addEmployee() { let fg = this.formBuilder.group(new Employee()); this.empFormArray.push(fg); } deleteEmployee(idx: number) { this.empFormArray.removeAt(idx); } loadTeam(name: string) { this.teamMngService.getTeamByName(name) .subscribe(team => { this.createFormWithDefaultData(team); }); } createFormWithDefaultData(team: Team) { //this.teamForm.patchValue(team); this.teamForm.patchValue({ teamName: team.teamName, teamManager: team.teamManager, teamDept: team.teamDept }); let employeeFormGroups = team.employees.map(employee => this.formBuilder.group(employee)); let employeeFormArray = this.formBuilder.array(employeeFormGroups); this.teamForm.setControl('employees', employeeFormArray); } onFormSubmit() { let data = JSON.stringify(this.teamForm.value); console.log('-----Team in JSON Format-----'); console.log(data); let team: Team = this.teamForm.value; this.teamMngService.saveTeam(team); this.formSubmitted = true; this.teamForm.reset(); } resetTeamForm() { this.teamForm.reset({ teamName: 'Java Team', teamManager: 'Yogi' }); } }
<h3>Create New Team <button type="button" (click)="loadTeam('Java Team')"> Load Default Team </button> <button type="button" (click)="resetTeamForm()"> Reset </button> </h3> <div *ngIf="formSubmitted && teamForm.pristine" class="submitted"> Form submitted successfully. </div> <div class="team"> <form [formGroup]="teamForm" (ngSubmit)="onFormSubmit()"> <p>Team Name : <input formControlName="teamName"> <br /><label *ngIf="teamForm.get('teamName')?.invalid && teamForm.get('teamName')?.dirty" class="error"> Team name is required. </label> </p> <p>Team Manager : <input formControlName="teamManager"></p> <b>Department :</b><br> <div formGroupName="teamDept" class="department"> <p>Department Head : <input formControlName="deptHead"></p> <p>Department Name : <input formControlName="deptName"></p> </div> <div class="all-emp"> <b> Employees in Team :</b><br><br> <div formArrayName="employees"> <div *ngFor="let emp of empFormArray.controls; let idx = index" [formGroupName]="idx" class="employee"> <p> <b>Employee : {{idx + 1}}</b> </p> <p>Emp Id : <input formControlName="empId"></p> <p>Emp Name : <input formControlName="empName"></p> <p>Skill : <select formControlName="skill"> <option *ngFor="let skill of allSkills | async" [ngValue]="skill.name"> {{ skill.displayName }} </option> </select> </p> <p><button type="button" (click)="deleteEmployee(idx)">Delete</button></p> </div> </div> <button type="button" (click)="addEmployee()">Add More Employee</button> </div> <br /> <button [disabled]="teamForm.invalid">SUBMIT</button> </form> </div>
import { NgModule } from '@angular/core'; import { BrowserModule } from '@angular/platform-browser'; import { ReactiveFormsModule } from '@angular/forms'; import { AppComponent } from './app.component'; import { TeamManagementComponent } from './team-management.component'; import { TeamManagementService } from './team-management.service'; @NgModule({ imports: [ BrowserModule, ReactiveFormsModule ], declarations: [ AppComponent, TeamManagementComponent ], providers: [ TeamManagementService ], bootstrap: [ AppComponent ] }) export class AppModule { }
.employee { border: 2px solid blue; width: 275px; } .department { border: 2px solid blue; width: 275px; } .team { border: 3px solid black; width: 300px; } .all-emp { border: 3px solid black; width: 275px; } .error{ color: red; } .submitted{ color: green; font-size: 20px; }
Run Application
To run the demo application, find following steps.1. Download source code using download link given below on this page.
2. Use downloaded src in your Angular CLI application. To install Angular CLI, find the link.
3. Run ng serve using command prompt.
4. Access the URL http://localhost:4200
Find the print screen of the output.

References
FormBuilderReactive Forms