昨天介紹了 formControl 如何使用 今天來介紹 formArray 這部份老實說花了我不少時間才懂 XD
今天要在表單裡加上喜好,喜好會有很多,所以我們來使用 formArray 處理,預設值先給它一個空陣列
建立動態表單 (FormArray)
ts 程式裡的 favorites 是一組 formArray 我們先將這組 formArray 獨立出來操控它
export class FormComponent implements OnInit {
form: FormGroup = new FormGroup({
name: new FormControl(),
phone: new FormControl(),
favorites: new FormArray([]),
});
get favorites() {
return this.form.get('favorites') as FormArray;
}
}
.html
...略
<div
formArrayName="favorites"
*ngFor="let fav of favorites.controls; let idx = index"
>
<div [formGroupName]="idx">
<ng-container *ngIf="idx === 0">
<label for="">favorites:</label>
<br />
</ng-container>
<input formControlName="favorite" type="text" [value]="" />
<button (click)="removeField(idx, $event)">移除</button>
</div>
</div>
到目前為止,畫面上是沒東西的,原因是我們還沒為 FormArray 做表單控制元件
為 FormArray 新增一組 FormGroup
.html
<div [formGroupName]="idx">
<ng-container *ngIf="idx === 0">
<label for="">favorites:</label>
<!-- 加上新增按鈕 -->
<button (click)="addField()">新增</button>
<br />
</ng-container>
<input formControlName="favorite" type="text" />
<button (click)="removeField(idx)">移除</button>
</div>
建立一個新增方法 addField
在 ngOnInit 時執行它,同時也在 html 裡加上新增按鈕
.ts
ngOnInit(): void {
this.addField();
}
addField(): void {
this.favorites.push(
new FormGroup({
id: new FormControl(),
favorite: new FormControl(),
})
)
}
favorites 裡會是一個陣列, 所以當我們要新增一組陣列的時後就則是使用 push 的方式新增一組 FormGroup, 裡面再包 FormControl,如此一來 formArray 就新增一組新的資料了
FormArray 一開始需要呈現多筆資料
在實作裡常常從 api 裡撈出一些資料 需要一開始的時後就呈現,所以在 ngOnInit 讀到資料的時後,就將資料餵給表單
.ts
// 預設資料表
favoritesOptions = [
{ id: 1, favorite: "book" },
{ id: 2, favorite: "sleep" },
{ id: 3, favorite: "shopping" },
];
ngOnInit(): void {
this.favoritesOptions.forEach((e) => {
this.favorites.push(
new FormGroup({
id: new FormControl(e.id),
favorite: new FormControl(e.favorite),
})
);
});
}
FormArray 移除一筆資料
在 template 做一個移除按鈕
.html
<ng-container
formArrayName="favorites"
*ngFor="let fav of favorites.controls; let idx = index"
>
<div [formGroupName]="idx">
<mat-form-field appearance="legacy">
<mat-label>favorites</mat-label>
<input formControlName="favorite" type="text" matInput />
<!-- 新增移除按鈕 -->
<mat-icon (click)="removeField(idx)" matSuffix>delete</mat-icon>
</mat-form-field>
</div>
</ng-container>
.ts
removeField(index: number): void {
// 剩下一筆時不給刪!
if (this.favorites.value.length > 1) {
this.favorites.removeAt(index);
}
}
這裡要注意的是,removeAt 裡面要帶的值 是 formArray value 裡的 index
(索引)
如此一來,就能對表單做移除的動作了!
參考資料:
明天就來說說 setValue 與 patchValue 的差異,這裡也是踩了不少雷 XD