A Variable Number of Fields
FormArray — Dynamic Lists
FormArray holds an ordered list of FormControl or FormGroup — perfect for letting the user add or remove rows of fields.
What you'll learn
- Create a FormArray
- push, insert, and removeAt
- Iterate with formArrayName
FormControl is a single field. FormGroup is a fixed-shape object. FormArray is a list whose length you control at runtime.
Building One
import { Component, inject } from '@angular/core';
import { FormArray, FormControl, FormBuilder, ReactiveFormsModule } from '@angular/forms';
@Component({
selector: 'app-tags',
standalone: true,
imports: [ReactiveFormsModule],
template: `...`,
})
export class TagsComponent {
private fb = inject(FormBuilder);
form = this.fb.group({
name: '',
tags: this.fb.array<FormControl<string>>([]),
});
get tags() {
return this.form.controls.tags;
}
add() {
this.tags.push(new FormControl('', { nonNullable: true }));
}
remove(i: number) {
this.tags.removeAt(i);
}
} Rendering With formArrayName
<form [formGroup]="form">
<input formControlName="name" placeholder="Name" />
<div formArrayName="tags">
@for (ctrl of tags.controls; track $index) {
<div>
<input [formControlName]="$index" />
<button type="button" (click)="remove($index)">Remove</button>
</div>
}
</div>
<button type="button" (click)="add()">Add tag</button>
</form> The formArrayName directive scopes the inner formControlName values to indices into the array.
Useful Methods
array.push(control)— appendarray.insert(i, control)— insert at indexarray.removeAt(i)— remove at indexarray.clear()— empty itarray.at(i)— get the i-th controlarray.length— current count
When you push or remove, the form’s overall validity and value update immediately.
Nested FormGroups →