FormArray allows dynamic addition and removal of fields - like adding new techniques to a samurai's arsenal!
1import { FormArray, FormBuilder, FormGroup } from '@angular/forms';
2
3interface SkillForm {
4 name: FormControl<string>;
5 level: FormControl<number>;
6}
7
8@Component({
9 template: \`
10 <form [formGroup]="samuraiForm" (ngSubmit)="onSubmit()">
11 <input formControlName="name" placeholder="Samurai name">
12
13 <h3>Skills</h3>
14 <div formArrayName="skills">
15 @for (skill of skills.controls; track $index; let i = $index) {
16 <div [formGroupName]="i" class="skill-row">
17 <input formControlName="name" placeholder="Skill name">
18 <input formControlName="level" type="number" placeholder="Level">
19 <button type="button" (click)="removeSkill(i)">❌</button>
20 </div>
21 }
22 </div>
23
24 <button type="button" (click)="addSkill()">➕ Add skill</button>
25
26 <button type="submit">Save</button>
27 </form>
28 \`
29})
30export class DynamicFormComponent {
31 private fb = inject(FormBuilder);
32
33 samuraiForm = this.fb.group({
34 name: ['', Validators.required],
35 skills: this.fb.array<FormGroup<SkillForm>>([])
36 });
37
38 // Getter for easy access
39 get skills(): FormArray<FormGroup<SkillForm>> {
40 return this.samuraiForm.get('skills') as FormArray;
41 }
42
43 addSkill(): void {
44 const skillGroup = this.fb.group({
45 name: ['', Validators.required],
46 level: [1, [Validators.min(1), Validators.max(10)]]
47 });
48 this.skills.push(skillGroup);
49 }
50
51 removeSkill(index: number): void {
52 this.skills.removeAt(index);
53 }
54
55 onSubmit(): void {
56 if (this.samuraiForm.valid) {
57 console.log(this.samuraiForm.value);
58 // { name: 'Musashi', skills: [{ name: 'Kendo', level: 5 }, ...] }
59 }
60 }
61}1loadSamurai(samurai: Samurai): void {
2 // Reset and set simple fields
3 this.samuraiForm.patchValue({
4 name: samurai.name
5 });
6
7 // Clear and add skills
8 this.skills.clear();
9 samurai.skills.forEach(skill => {
10 this.skills.push(this.fb.group({
11 name: [skill.name, Validators.required],
12 level: [skill.level]
13 }));
14 });
15}