FormArray — Dynamic Lists

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.

4 min read Level 2/5 #angular#forms#dynamic
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) — append
  • array.insert(i, control) — insert at index
  • array.removeAt(i) — remove at index
  • array.clear() — empty it
  • array.at(i) — get the i-th control
  • array.length — current count

When you push or remove, the form’s overall validity and value update immediately.

Nested FormGroups →