Angular FormArray Example
August 26, 2021
This page will walk through Angular FormArray
example. Angular FormArray
tracks the value and validity state of an array of FormControl
, FormGroup
or FormArray
instances.
Let us create an array of
FormControl
using FormArray
.
const fmArr = new FormArray([ new FormControl(), new FormControl() ]);
Let us understand using
FormArray
in detail.
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
FormArray
Find the constructor ofFormArray
class used to create its new instance.
constructor(controls: AbstractControl[], validatorOrOpts?: ValidatorFn | AbstractControlOptions | ValidatorFn[], asyncValidator?: AsyncValidatorFn | AsyncValidatorFn[])
FormControl
, FormGroup
or FormArray
instances.
2. validatorOrOpts : This is optional. This is the second argument in which we pass a synchronous validator or its array.
3. asyncValidator : This is optional. This is the third argument in which we pass an async validator or its array.
Find some of the methods of
FormArray
class.
at(): Returns the
AbstractControl
instance for the given index. The AbstractControl
is the base class for FormControl
, FormGroup
and FormArray
classes.
push(): Inserts the new
AbstractControl
at the end of array.
insert(): Inserts a new
AbstractControl
at the given index in the array.
removeAt(): Removes the control at the given index in the array.
setControl(): Sets a new control replacing the old one.
setValue(): Sets the value to every control of this
FormArray
.
patchValue(): Patches the value to available controls starting from index 0.
reset(): Resets the values.
getRawValue(): The aggregate value of the array.
clear(): Removes all controls in this
FormArray
.
With FormGroup
Find the code to create aFormGroup
using FormArray
.
studentForm = new FormGroup({ name: new FormControl('', [ Validators.required ]), classmates: new FormArray([ new FormControl('Mahesh'), new FormControl('Krishna') ]) }); get name() { return this.studentForm.get('name') as FormControl; } get classmates() { return this.studentForm.get('classmates') as FormArray; }
FormArrayName
TheFormArrayName
syncs a nested FormArray
to a DOM element. It is used under formGroup
in HTML template. It accepts the string name of FormArray
registered in the FormGroup
created in the TypeScript. The selector of FormArrayName
is formArrayName
.
Find the HTML template code for the above form group.
<form [formGroup]="studentForm" (ngSubmit)="onFormSubmit()"> <div> Name: <input formControlName="name"> <label *ngIf="name.hasError('required')"> Enter Name. </label> </div> Classmates: <div formArrayName="classmates"> <div *ngFor="let cm of classmates.controls; index as i"> <input [formControlName]="i"> </div> </div> <button>SUBMIT</button> </form>
Using FormBuilder.array()
TheFormBuilder.array()
constructs a new FormArray
. The FormBuilder
has following methods.
group() : Construct a new
FormGroup
instance.
control() : Construct a new
FormControl
.
array() : Constructs a new
FormArray
.
Find the
FormBuilder.array()
method signature.
array(controlsConfig: any[], validatorOrOpts?: ValidatorFn | AbstractControlOptions | ValidatorFn[], asyncValidator?: AsyncValidatorFn | AsyncValidatorFn[]): FormArray
validatorOrOpts: This is optional. A synchronous validator function, or an array of such functions.
asyncValidator: This is optional. A single async validator or array of async validator functions.
Find the code snippet to create
FormGroup
using FormBuilder.group()
method and FormArray
using FormBuilder.array()
method.
studentForm = this.formBuilder.group({ name: new FormControl('', [ Validators.required ]), classmates: this.formBuilder.array([ new FormControl('Mahesh'), new FormControl('Krishna') ]) });
FormArray Validation
We know thatFormArray
accepts three arguments, first for controls, second for synchronous validators and third for async validators.
Here in our example, we are using only synchronous validators.
teamForm = this.formBuilder.group({ ------ employees: this.formBuilder.array([ new FormControl() ], [Validators.required, Validators.maxLength(5)]) });
FormArray
using FormBuilder.array()
method with required
and maxLength
validators.
Using
required
validator means, the FormArray
must contain atleast one control i.e. array size must be minimum 1.
Using
maxLength(5)
validator means, the FormArray
must not contain more than 5 controls i.e. array size cannot be more than 5.
The error messages can be displayed in HTML template as following.
<label *ngIf="employees?.errors?.required" class="error"> Employee required. </label> <label *ngIf="employees?.errors?.maxlength" class="error"> Max number of Employee can be 5 only. </label>
Using FormArray Methods
Let us understand how to useFormArray
methods. Find the code snippet of a form group.
teamForm = this.formBuilder.group({ ------ employees: this.formBuilder.array([ new FormControl() ]) }); get employees() { return this.teamForm.get('employees') as FormArray; }
FormArray
methods.
1. at(): Returns the control instance for the given index.
const emp = this.employees.at(2); console.log(emp.value);
2. push(): Inserts the new control at the end of the array.
addEmployeeControl() { this.employees.push(new FormControl()); }
deleteEmployeeControl(index: number) { this.employees.removeAt(index); }
insertEmployeeControl() { this.employees.insert(1, new FormControl()); }
5. setControl(): Sets a new control replacing the old one.
setEmployeeControl() { this.employees.setControl(1, new FormControl('Krishna')); }
6. setValue(): Sets the value to every control of the array.
setEmployeeValue() { this.employees.setValue(['Mahesh', 'Vishal', 'Krishna']); }
FormArray
of size 3. The value will be set to all the three controls. If the array size of FormArray
is not 3, the setValue
will throw error.
7. patchValue(): Patches the value to available controls starting from index 0.
patchEmployeeValue() { this.employees.patchValue(['Mahesh', 'Vishal', 'Krishna']); }
FormArray
is not 3, the patchValue
will not throw error.
8. reset(): Resets the values of all controls of the array.
resetEmployees() { this.employees.reset(); }
clearEmployeeControls() { this.employees.clear(); }
const rawVal = this.employees.getRawValue(); console.log(rawVal);
Complete Example
team-management.component.tsimport { Component, OnInit } from '@angular/core'; import { FormControl, FormArray, Validators, FormBuilder } from '@angular/forms'; import { TeamManagementService } from './team-management.service'; @Component({ selector: 'app-team', templateUrl: './team-management.component.html' }) export class TeamManagementComponent implements OnInit { constructor( private formBuilder: FormBuilder, private teamMngService: TeamManagementService) { } ngOnInit() { } teamForm = this.formBuilder.group({ teamName: ['', Validators.required], employees: this.formBuilder.array([ new FormControl() ], [Validators.required, Validators.maxLength(5)]) }); get teamName() { return this.teamForm.get('teamName') as FormControl; } get employees() { return this.teamForm.get('employees') as FormArray; } addEmployeeControl() { this.employees.push(new FormControl()); } deleteEmployeeControl(index: number) { this.employees.removeAt(index); } insertEmployeeControl() { this.employees.insert(1, new FormControl()); } setEmployeeControl() { this.employees.setControl(2, new FormControl('Shiv')); } setEmployeeValue() { this.clearEmployeeControls(); this.addEmployeeControl(); this.addEmployeeControl(); this.addEmployeeControl(); this.employees.setValue(['Mahesh', 'Vishal', 'Krishn']); } patchEmployeeValue() { this.employees.patchValue(['Mahesh', 'Vishal', 'Krishn']); } resetEmployees() { this.employees.reset(); } clearEmployeeControls() { this.employees.clear(); } onFormSubmit() { const emp = this.employees.at(0); console.log(emp.value); const rawVal = this.employees.getRawValue(); console.log(rawVal); this.teamMngService.saveTeam(this.teamForm.value); this.teamForm.reset(); } }
<h3>Create New Team</h3> <div class="team"> <form [formGroup]="teamForm" (ngSubmit)="onFormSubmit()"> <p><b>Team Name : </b> <input formControlName="teamName"> <br /><label *ngIf="teamName?.dirty && teamName?.errors?.required" class="error"> Team name required. </label> </p> <b> Employees in Team :</b><br><br> <label *ngIf="employees?.errors?.required" class="error"> Employee required. </label> <label *ngIf="employees?.errors?.maxlength" class="error"> Max number of Employee can be 5 only. </label> <div formArrayName="employees"> <div *ngFor="let emp of employees.controls; let i = index" class="employee"> <p> <b>Employee {{i + 1}} : </b> <input [formControlName]="i"> <button type="button" (click)="deleteEmployeeControl(i)">Delete</button> </p> </div> </div> <button type="button" (click)="addEmployeeControl()">Add More Employee</button><br/> <button type="button" (click)="insertEmployeeControl()">Insert Employee at number 2</button><br/> <button type="button" (click)="patchEmployeeValue()">Patch Value</button><br/> <button type="button" (click)="setEmployeeValue()">Create Default Employee List</button><br/> <button type="button" (click)="setEmployeeControl()">Set Default Employee at number 3</button><br/> <button type="button" (click)="resetEmployees()">Reset Employees</button><br/> <button type="button" (click)="clearEmployeeControls()">clear Employees</button><br/><br/> <button [disabled]="teamForm.invalid">SUBMIT</button> </form> </div>
export interface Team { teamName: string; employees: string[]; }
import { Injectable } from '@angular/core'; import { Team } from './team'; @Injectable() export class TeamManagementService { saveTeam(team: Team) { console.log('------------TEAM------------'); console.log('Team Name: ' + team.teamName); console.log('----- Employee Detail -----'); for (let emp of team.employees) { console.log('Emp Name: ' + emp); console.log('-------------------'); } } }
import { Component } from '@angular/core'; @Component({ selector: 'app-root', template: ` <app-team></app-team> ` }) export class AppComponent { }
.team { border: 3px solid black; width: 400px; } .employee { border: 2px solid blue; width: 350px; } .error{ color: red; } .submitted{ color: green; font-size: 20px; }
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 { }
Run Application
To run the application, find the 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
FormArrayFormBuilder