Angular Reactive Form 响应式表单 (formArray)

昨天介绍了 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


<<:  Day9 支持向量机(Support Vector Machine)

>>:  [Day13] 学 Reactstrap 就离 React 更近了 ~ Navbar ‧ 初识篇

Day25,Kubeapps一日体验

kubeapps是一个由vmware/bitnami主导的开源项目,主旨为在kubernetes中让...

Day22 Gin with CORS

What is CORS CORS全名为Cross-Origin Resource Sharing ...

[ Day 5 ] - 物件

物件 物件的格式 会使用 { } 前後包住资料集 内容会有属性和值 let shop = { Nam...

Day 28 : 案例分享(8.2) 讯息、邮件与线上会议 - 线上会议 odoo15 新功能

功能说明 odoo在其运用中,讯息及讨论,一直是个标准的内附功能 在各单据中都可直接发送讯息给相关内...

DAY 01 前言

前言 第一次参加铁人赛,真是有点小紧张哎嘿,虽然自己平常也是有在写一些技术文件,但是三十天连载这种大...