The Angular FormArray example shows how to use the FormArray. The FormArray allows us to add controls dynamically to the reactive forms. In this example, we will take a very simple task of dynamically adding/removing skills to an employee form.
Table of Contents
What is FormArray
The FormArray is a way to manage the collection of Form Controls in Angular. The controls can be a FormGroup, FormControl, or another FormArray.
We can group Form Controls in Angular forms in two ways. One is using the FormGroup and the other one is FormArray. The difference is how they implement it. In FormGroup controls becomes a property of the FormGroup. Each control is represented as key-value pair. While in FormArray, the controls become part of an array
Because it is implemented as an Array, it makes it easier dynamically add controls.
FormArray Example
Let us build a simple app, which allows us to add the new skill of a person dynamically.
Import FormArray
To use FormArray, First, you need to import the FormArray from the Angular Forms Module.
1 2 3 | import { FormGroup, FormControl,FormArray, FormBuilder } from '@angular/forms' |
Build a Form Model
Build a form model skillsForm using the FormBuilder. Our Form has two fields. name of the person and his skills. Since the person can have more than one skill, we define skills as FormArray.
1 2 3 4 5 6 7 8 9 10 11 12 | skillsForm: FormGroup; constructor(private fb:FormBuilder) { this.skillsForm = this.fb.group({ name: '', skills: this.fb.array([]) , }); } |
Next, a getter method skills, which returns the skills FormArray from the skillsForm
1 2 3 4 5 | get skills() : FormArray { return this.skillsForm.get("skills") as FormArray } |
The skill FormGroup
We need to capture two fields under each skill. Name of the skill & years of exp. Hence we create a FormGroup with two fields. The method newSkill creates a new FormGroup and returns it. Note that we won’t be able to assign a name to Form Group.
1 2 3 4 5 6 7 8 | newSkill(): FormGroup { return this.fb.group({ skill: '', exp: '', }) } |
Dynamically adding skill
Now, we need to add a new skill to the skills FormArray. Since it is an array we can use the push method to add the new skill using the the newSkill method. Note that newSkill() method returns a FormGroup. The name of the FormGroup is its Index in the FormArray.
1 2 3 4 5 | addSkills() { this.skills.push(this.newSkill()); } |
Dynamically Removing Skill
Use the removeAt method to remove the element from the skills FromArray.
1 2 3 4 5 | removeSkill(i:number) { this.skills.removeAt(i); } |
Submit
1 2 3 4 5 | onSubmit() { console.log(this.skillsForm.value); } |
Template
Now, it is time to build the Template. Use the [formGroup]="skillsForm" to bind the form to the skillsForm model. The formControlName="name" directive binds the name input element to name property of the skillsForm
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | <form [formGroup]="skillsForm" (ngSubmit)="onSubmit()"> <p> <label for="name">Name </label> <input type="text" id="name" name="name" formControlName="name"> </p> <p> <button type="submit">Submit</button> </p> </form> |
Binding FormArray to Template
We use the formArrayName directive to bind the skills form array to the div element. Now the div and anything inside the div element is bound to the skills form array.
1 2 3 4 5 | <div formArrayName="skills"> </div> |
Inside the div use ngFor to loop through each element of skills FormArray. let i=index will store the index value of the array in template local variable i. We will make use of it to remove the element from the skills array.
1 2 3 4 5 6 7 | <div formArrayName="skills"> <div *ngFor="let skill of skills().controls; let i=index"> </div> </div> |
Each element under the skills is a FormGroup. We do not have a name to the FormGroup. The Index of the element is automatically assigned as the name for the element.
Hence we use the [formGroupName]="i" where i is the index of the FormArray to bind the FormGroup to the div element.
1 2 3 4 5 6 7 8 9 | <div formArrayName="skills"> <div *ngFor="let skill of skills().controls; let i=index"> <div [formGroupName]="i"> </div> </div> </div> |
Finally, we add the controls using the formControlName directive.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | Skills: <div formArrayName="skills"> <div *ngFor="let skill of skills().controls; let i=index"> <div [formGroupName]="i"> {{i}} skill name : <input type="text" formControlName="skill"> exp: <input type="text" formControlName="exp"> <button (click)="removeSkill(i)">Remove</button> </div> </div> </div> |
Also, pass the index i to removeSkill
1 2 3 | <button (click)="removeSkill(i)">Remove</button> |
Finally, call the addSkills method to add new skills.
1 2 3 4 5 | <p> <button type="button" (click)="addSkills()">Add</button> </p> |
That’s it

Source Code
app.component.ts
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 | import { Component, ViewChild, ElementRef } from '@angular/core'; import { FormGroup, FormControl,FormArray, FormBuilder } from '@angular/forms' @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) export class AppComponent { title = 'FormArray Example in Angular Reactive forms'; skillsForm: FormGroup; constructor(private fb:FormBuilder) { this.skillsForm = this.fb.group({ name: '', skills: this.fb.array([]) , }); } get skills() : FormArray { return this.skillsForm.get("skills") as FormArray } newSkill(): FormGroup { return this.fb.group({ skill: '', exp: '', }) } addSkills() { this.skills.push(this.newSkill()); } removeSkill(i:number) { this.skills.removeAt(i); } onSubmit() { console.log(this.skillsForm.value); } } export class country { id: string; name: string; constructor(id: string, name: string) { this.id = id; this.name = name; } } |
app.component.html
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | <form [formGroup]="skillsForm" (ngSubmit)="onSubmit()"> <p> <label for="name">Name </label> <input type="text" id="name" name="name" formControlName="name"> </p> Skills: <div formArrayName="skills"> <div *ngFor="let skill of skills().controls; let i=index"> <div [formGroupName]="i"> {{i}} skill name : <input type="text" formControlName="skill"> exp: <input type="text" formControlName="exp"> <button (click)="removeSkill(i)">Remove</button> </div> </div> </div> <p> <button type="submit">Submit</button> </p> </form> <p> <button type="button" (click)="addSkills()">Add</button> </p> {{this.skillsForm.value | json}} |
References
Summary
In this tutorial, we learned how to create a simple FormArray Example app.
Complete List of Articles on Angular Forms
- Angular Forms Tutorial: Fundamental & Concepts
- Template Driven Forms in Angular
- Set Value in Template Driven forms in Angular
- Reactive Forms in Angular
- FormBuilder in Reactive Forms
- SetValue & PatchValue in Angular
- StatusChanges in Angular Forms
- ValueChanges in Angular Forms
- FormControl
- FormGroup
- FormArray Example
- Build Dynamic or Nested Forms using FormArray
- Validations in Reactive Forms in Angular
- Custom Validator in Reactive Forms
- Passing Parameter to Custom Validator in Reactive Forms
- Inject Service into Custom Validator
- Validation in Template Driven Forms
- Custom Validator in Template Driven Forms



if some user wants to add functionality that when he filled detail and click on add button than it display and form reset and he add in same box new data
So if I have a array of objects in the format {id: number, name: string, checked: boolean} and want to create a form of checkboxes, how to do it using the formArray? Is there way to insert a required validator to this form?
idk
You’re awsome!
need explanation for How to get the formarray controls to display error messages in HTML
Great!!
How can you start with already one ( or more) skill(s) in the form?
i tried to place the addSkills function inside the array but it doesn’t work
this.skillsForm = this.fb.group({
name: ”,
skills: this.fb.array([
this.addSkills()
]) ,
});
also put this formArray hardcode inside the formGrtoup doesn’t works
[[ {
“name”: “”,
“skills”: [
{
“skill”: “”,
“exp”: “”
}
]
} ]]
You should add form group While hardcoding .
this.skillForm = this.fb.group({
name : ” ,
skills : this.fb.array([this.fb.group({skill:’Angular’,exp : ‘2’ })])
})
error TS6234: This expression is not callable because it is a ‘get’ accessor. Did you mean to use it without ‘()’?
Type ‘FormArray’ has no call signatures.
11
This is giving Error. Any suggestion?
jsut remove ()
Terrific tutorial!
I was struggling to create a form to add a printer from the set of all known printers in the system but this tutorial gave me the way.
Thanks!
“Table of Content” should actually be “Table of Contents”
woow very well explained thanks
Incorrect: Below line gives error => ‘skills’ is not callable
let skill of skills().controls
Correct:
let skill of skills.controls
Explanation: skills is not a function, it is a getter.
Source: https://angular.io/guide/reactive-forms
Thanks you so much, just saved my life there.
thanks…. you really helped
Great article!
needs to be;
*ngFor=”let skill of skills().controls; let i=index”
needs to be
*ngFor=”let skill of skills().controls; let i=index”
Thanks
*ngFor=”let skill of skills().controls; let i=index” is correct
This is incorrect
The correct is:
incorrect: let skill of skillsControl.controls; let i=index
correct: let skill of skills.controls; let i=index
Thanks. Updated the code
thanks
in this you not explained how to change value of formarray controls
Yes. We are planning to write separate article on it.