Angular FormArray Validation
September 02, 2021
Angular FormArray
tracks the value and validity state of an array of FormControl
, FormGroup
or FormArray
instances. To create a FormArray
, we can pass an array of FormControl
or FormGroup
. A FormArray
is called validated only if its FormControl
or FormGroup
are validated. We can validate FormArray
with synchronous and async validators.
On this page we will create a reactive form using
FormBuilder
and validate it.
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 Validation
We can pass following arguments to instantiateFormArray
.
FormArray(controls: AbstractControl[], validatorOrOpts?: ValidatorFn | AbstractControlOptions | ValidatorFn[], asyncValidator?: AsyncValidatorFn | AsyncValidatorFn[])
FormControl
, FormGroup
or FormArray
.
2. Second argument is for sync validators. It is optional.
3. Third argument is for async validators. It is also optional.
Find the sample example.
We are using
Validators.required
at FormArray
level. It means the size of FormArray
must be greater than zero.
formArray = new FormArray([], [Validators.required]); ngOnInit() { console.log(this.formArray.status); this.formArray.push(new FormControl()); console.log(this.formArray.status); }
INVALID VALID
FormArray
then validity status was invalid and when we pushed a control then FormArray
became valid.
FormArray Validation using FormControl
SupposeFormArray
is the array of FormControl
. Then FormArray
will not be considered validated if any of the FormControl
is invalid. Find the code snippet.
formArray = new FormArray([ new FormControl('', [Validators.required]), new FormControl('', [Validators.required, Validators.minLength(3)]) ]); ngOnInit() { console.log(this.formArray.status); this.formArray.setValue(["AA", "BBB"]); console.log(this.formArray.status); }
INVALID VALID
FormArray
is containing two FormControl
and they need to be validated and only when FormArray
will be considered validated.
FormArray Validation using FormGroup
SupposeFormArray
contains the array of FormGroup
and each FormGroup
contains FormControl
with some validators. FormArray
will be considered validated only if all the FormGroup
are validated and FormGroup
will be validated only if all the FormControl
are validated. Find the code snippet.
formArray = new FormArray([ new FormGroup({ name: new FormControl('', [Validators.required]), age: new FormControl('', [Validators.min(18)]) }), new FormGroup({ name: new FormControl('', [Validators.required]), age: new FormControl('', [Validators.min(18)]) })], ); ngOnInit() { console.log(this.formArray.controls[0].status); console.log(this.formArray.controls[1].status); console.log(this.formArray.status); this.formArray.setValue([{name: "Mahesh", age: 20}, {name: "Krishna", age: 25}]); console.log("---After setting value---"); console.log(this.formArray.controls[0].status); console.log(this.formArray.controls[1].status); console.log(this.formArray.status); }
INVALID INVALID INVALID ---After setting value--- VALID VALID VALID
FormArray Validation Example with FormBuilder
We will create a reactive form usingFormBuilder
which has methods such as group()
to create FormGroup
, control()
to create FormControl
and array()
to create FormArray
.
In our example we will create
FormArray
that will contain array of FormGroup
and each FormGroup
will contain some FormControl
with validators. At run time we will push and remove controls from FormArray
instance.
Find the code snippet to create team form.
this.teamForm = this.formBuilder.group({ teamName: ['', Validators.required], employees: this.formBuilder.array( [this.createEmpFormGroup()], [Validators.required, Validators.maxLength(5)]) });
createEmpFormGroup()
method is creating a FormGroup
as following. This will add an employee in team.
createEmpFormGroup() { return this.formBuilder.group({ empName: ['', [Validators.required]], age: ['', [Validators.required, Validators.min(21)]], skill: ['', [Validators.required]], }) }
FormArray
and its elements, find the getter method for employees
form array control.
get employees(): FormArray { return this.teamForm.get('employees') as FormArray; }
FormArray
validation errors for custom error messages as following.
<label *ngIf="employees.errors?.required"> Add Employees. </label> <label *ngIf="employees.errors?.maxlength" class="error"> Maximum number of Employees can be 5. </label> <label *ngIf="employees.controls[i].get('age').errors?.required"> Age required. </label> <label *ngIf="employees.controls[i].get('age').errors?.min"> Minimum age is 21. </label>
i
is the index of employees
form array.
Find the print screen of output of our example. When we try to submit the form without validations, we will get following error messages.

team-management.component.ts
import { Component, OnInit } from '@angular/core'; import { FormGroup, FormArray, Validators, FormBuilder } from '@angular/forms'; import { Observable } from 'rxjs'; import { TeamManagementService } from './team-management.service'; import { Team } from './team'; import { Employee } from './employee'; @Component({ selector: 'app-team', templateUrl: './team-management.component.html' }) export class TeamManagementComponent implements OnInit { teamForm = {} as FormGroup; isValidFormSubmitted: boolean | null = null; allSkills: Observable<any[]>; constructor( private formBuilder: FormBuilder, private teamMngService: TeamManagementService) { this.allSkills = this.teamMngService.getSkills(); } ngOnInit() { this.teamForm = this.formBuilder.group({ teamName: ['', Validators.required], employees: this.formBuilder.array( [this.createEmpFormGroup()], [Validators.required, Validators.maxLength(5)]) }); } createEmpFormGroup() { return this.formBuilder.group({ empName: ['', [Validators.required]], age: ['', [Validators.required, Validators.min(21)]], skill: ['', [Validators.required]], }) } get teamName() { return this.teamForm.get('teamName'); } get employees(): FormArray { return this.teamForm.get('employees') as FormArray; } addEmployee() { let fg = this.createEmpFormGroup(); this.employees.push(fg); } deleteEmployee(idx: number) { this.employees.removeAt(idx); } onFormSubmit() { this.isValidFormSubmitted = false; if (this.teamForm.invalid) { return; } this.isValidFormSubmitted = true; let team: Team = this.teamForm.value; this.teamMngService.saveTeam(team); this.teamForm.reset(); } resetTeamForm() { this.teamForm.reset(); } }
<h3>Create New Team</h3> <div *ngIf="isValidFormSubmitted" class="submitted"> Form submitted successfully. </div> <div class="team"> <form [formGroup]="teamForm" (ngSubmit)="onFormSubmit()"> <p>Team Name : <input formControlName="teamName"> <br /> <label *ngIf="teamName?.invalid && isValidFormSubmitted != null && !isValidFormSubmitted" class="error"> Team name is required. </label> </p> <div class="all-emp"> <b>Employees in Team:</b> <br> <label *ngIf="employees.errors?.required" class="error"> Add Employees. </label> <label *ngIf="employees.errors?.maxlength" class="error"> Maximum number of Employees can be 5. </label> <br> <div formArrayName="employees"> <div *ngFor="let emp of employees.controls; let i = index" [formGroupName]="i" class="employee"> <p> <b>Employee : {{i + 1}}</b> </p> <p>Name : <input formControlName="empName"> <br /> <label *ngIf="employees.controls[i].get('empName')?.errors?.required && isValidFormSubmitted != null && !isValidFormSubmitted" class="error"> Employee name required. </label> </p> <p>Age : <input formControlName="age"> <br /> <label *ngIf="employees.controls[i].get('age')?.errors?.required && isValidFormSubmitted != null && !isValidFormSubmitted" class="error"> Age required. </label> <label *ngIf="employees.controls[i].get('age')?.errors?.min && isValidFormSubmitted != null && !isValidFormSubmitted" class="error"> Minimum age is 21. </label> </p> <p>Skill : <select formControlName="skill"> <option *ngFor="let skill of allSkills | async" [ngValue]="skill.name"> {{ skill.displayName }} </option> </select> <br /> <label *ngIf="employees.controls[i].get('skill')?.errors?.required && isValidFormSubmitted != null && !isValidFormSubmitted" class="error"> Select skill. </label> </p> <p> <button type="button" (click)="deleteEmployee(i)">Delete</button> </p> </div> </div> <button type="button" (click)="addEmployee()">Add More Employee</button> </div> <br /> <button>SUBMIT</button> <button type="button" (click)="resetTeamForm()">RESET</button> </form> </div>
export class Employee { empName = null; age: number | null = null; skill = null; }
import { Employee } from './employee'; export interface Team { teamName: string; employees: Employee[]; }
import { Injectable } from '@angular/core'; import { of } from 'rxjs'; import { Team } from './team'; const ALL_SKILLS = [ { name: 'Java', displayName: 'Java' }, { name: 'Angular', displayName: 'Angular' }, { name: 'Dot Net', displayName: 'Dot Net' } ]; @Injectable({ providedIn: 'root' }) export class TeamManagementService { getSkills() { return of(ALL_SKILLS); } saveTeam(team: Team) { console.log('------------TEAM------------'); console.log('Team Name: ' + team.teamName); console.log('----- Employee Details -----'); for (let emp of team.employees) { console.log('Emp Name: ' + emp.empName); console.log('Emp age: ' + emp.age); console.log('Emp Skill: ' + emp.skill); console.log('-------------------'); } } }
import { Component } from '@angular/core'; @Component({ selector: 'app-root', template: ` <app-team></app-team> ` }) export class AppComponent { }
.employee { border: 2px solid blue; width: 275px; } .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'; @NgModule({ imports: [ BrowserModule, ReactiveFormsModule ], declarations: [ AppComponent, TeamManagementComponent ], providers: [], 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
References
Angular FormArrayAngular FormBuilder