A FormArray egy lehetőség az Angularban, hogy kezeljük a Form kontrollon belüli gyűjteményeket. A Form kontrollok lehetnek FormGroup, FormControl stb.
Minden kontroll egy kulcs-érték párt képvisel. A FormArray segítségével a kontroll egy egész tömböt tartalmaz.
A példánkban a telefonszámokat szeretnénk tömbben tárolni. Szeretnék lehetőséget új telefonszámok felvételére, ami új űrlapelemeket jelenít meg, és azok törlésére.
import { Component } from '@angular/core'; import { FormArray, FormBuilder, FormGroup, ReactiveFormsModule, Validators } from '@angular/forms'; import { RouterOutlet } from '@angular/router'; @Component({ selector: 'app-root', standalone: true, imports: [RouterOutlet, ReactiveFormsModule], templateUrl: './app.component.html', styleUrl: './app.component.scss' }) export class AppComponent { title = 'app01'; employeeForm!: FormGroup; constructor(private formBuilder: FormBuilder) { this.employeeForm = this.formBuilder.group({ name: ['', Validators.required], address: this.formBuilder.group({ city: '', street: '' }), salary: '', phones: this.formBuilder.array([]) }) } onSubmit() { if(this.employeeForm.valid) { console.log(this.employeeForm.value); } } get phones(): FormArray { return this.employeeForm.get('phones') as FormArray; } addPhone() { this.phones.push(this.newPhone()); } newPhone(): FormGroup { return this.formBuilder.group({ phone: '' }); } removePhone(i: number) { this.phones.removeAt(i); } }
A HTML sablonban a @for() direktívát használjuk, ami az Angular 17-ben jelent meg.
<form [formGroup]="employeeForm" (ngSubmit)="onSubmit()"> <div class="formGroup"> <label for="name">Név</label> <input type="text" id="name" formControlName="name" placeholder="Név"> </div> <div formGroupName="address"> <div class="formGroup"> <label for="city">Település</label> <input type="text" id="city" formControlName="city" placeholder="Település"> </div> <div class="formGroup"> <label for="street">Lakcím</label> <input type="text" id="street" formControlName="street" placeholder="Lakcím"> </div> </div> <div class="formGroup"> <label for="salary">Fizetés</label> <input type="text" id="salary" formControlName="salary" placeholder="Fizetés"> </div> <div> <button type="button" (click)="addPhone()">Telefont hozzáad</button> </div> <div formArrayName="phones"> @for (phone of phones.controls; track phone; let i = $index) { <div formGroupName="{{i}}"> <label for="phone">Telefonszám</label> <input type="text" formControlName="phone"> <button type="button" (click)="removePhone(i)">Törlés</button> </div> } </div> <div> <button type="submit" [disabled]="!employeeForm.valid"> Mehet </button> </div> </form>
Az adatokat ilyen formában kapjuk:
{ "name": "Csontos Ernő", "address": { "city": "Szeged", "street": "Tél utca 7" }, "salary": "398", "phones": [ { "phone": "(30) 894-2348" }, { "phone": "(70) 834-2483" } ] }
Egészítsük ki az alkalmazásunkat úgy, hogy a telefonszám típusát is tárolni tudjuk.
Javítsuk a newPhone() metódust:
newPhone(): FormGroup { return this.formBuilder.group({ type: '', phone: '' }); }
Javítsuk a phones tömb részt:
<div formArrayName="phones"> @for (phone of phones.controls; track phone; let i = $index) { <div formGroupName="{{i}}"> <label for="type">Típus</label> <input type="text" formControlName="type"> <br> <label for="phone">Telefonszám</label> <input type="text" formControlName="phone"> <button type="button" (click)="removePhone(i)">Törlés</button> </div> } </div>