何时使用 FormGroup 与 FormArray?

When to use FormGroup vs. FormArray?

FormGroup:

A FormGroup aggregates the values of each child FormControl into one object, with each control name as the key.

const form = new FormGroup({
  first: new FormControl('Nancy', Validators.minLength(2)),
  last: new FormControl('Drew')
});

FormArray:

A FormArray aggregates the values of each child FormControl into an array.

const arr = new FormArray([
  new FormControl('Nancy', Validators.minLength(2)),
  new FormControl('Drew')
]);

什么时候应该用一个代替另一个?

FormArray 是 FormGroup 的变体。关键区别在于它的数据被序列化为一个数组(而不是在 FormGroup 的情况下被序列化为一个对象)。当您不知道组中将存在多少控件时,这可能特别有用,例如动态表单。

让我试着通过一个简单的例子来解释。比方说,您有一个表单,您可以在其中捕获客户的比萨饼订单。然后你放置一个按钮让他们添加和删除任何特殊请求。这是组件的 html 部分:

<section>
  <p>Any special requests?</p>
  <ul formArrayName="specialRequests">
    <li *ngFor="let item of orderForm.controls.specialRequests.controls; let i = index">
      <input type="text" formControlName="{{i}}">
      <button type="button" title="Remove Request" (click)="onRemoveSpecialRequest(i)">Remove</button>
    </li>
  </ul>
  <button type="button" (click)="onAddSpecialRequest()">
    Add a Request
  </button>
</section>

这里是组件 class 定义和处理特殊请求:

constructor () {
  this.orderForm = new FormGroup({
    firstName: new FormControl('Nancy', Validators.minLength(2)),
    lastName: new FormControl('Drew'),
    specialRequests: new FormArray([
      new FormControl(null)
    ])
  });
}

onSubmitForm () {
  console.log(this.orderForm.value);
}

onAddSpecialRequest () {
  this.orderForm.controls
  .specialRequests.push(new FormControl(null));
}

onRemoveSpecialRequest (index) {
  this.orderForm.controls['specialRequests'].removeAt(index);
}

FormArray 比 FormGroup 更灵活,因为使用 "push"、"insert" 和 "removeAt" 比使用 FormGroup 的 "addControl"、"removeControl"、"setValue" 等。FormArray 方法确保控件在表单的层次结构中得到正确跟踪。

希望这对您有所帮助。

为了创建响应式表单,父 FormGroup 是必须的。此 FormGroup 可以进一步包含 formControls、子 formGroupsformArray

FormArray 可以进一步包含 formControls 数组或 formGroup 本身。

什么时候应该使用formArray?

请阅读这个漂亮的 post,它解释了 formArray

的用法

那个博客中有趣的例子是关于旅行的formGroup

使用 formControlformArray 的行程 formGroup 的结构类似于:

this.tripForm = this.fb.group({
    name: [name, Validators.required],
     cities: new FormArray(
       [0] ---> new FormGroup({
           name: new FormControl('', Validators.required),
               places: new FormArray(
                  [0]--> new FormGroup({
                      name: new FormControl('', Validators.required),
                         }),
                      [1]--> new FormGroup({
                         name: new FormControl('', Validators.required),
                      })
                  )
              }), 
       [1] ---> new FormGroup({
           name: new FormControl('', Validators.required),
           places: new FormArray(
               [0]--> new FormGroup({
                   name: new FormControl('', Validators.required),
               }),
               [1]--> new FormGroup({
                   name: new FormControl('', Validators.required),
               })
               )
      }))
})

不要忘记玩这个 DEMO,注意数组的用法 citiesplaces 的行程。

从 angular 文档中您可以看到

FormArray is an alternative to FormGroup for managing any number of unnamed controls. As with form group instances, you can dynamically insert and remove controls from form array instances, and the form array instance value and validation status is calculated from its child controls. However, you don't need to define a key for each control by name, so this is a great option if you don't know the number of child values in advance.

让我向您展示他们的示例,并尝试解释我是如何理解这一点的。可以看到来源here

假设一个表单 具有以下字段

  profileForm = this.fb.group({
    firstName: ['', Validators.required],
    lastName: [''],
    address: this.fb.group({
      street: [''],
      city: [''],
      state: [''],
      zip: ['']
    }),
    aliases: this.fb.array([
      this.fb.control('')
    ])
  });

这里我们有 firstNamelastNameaddressaliases 所有字段一起构成组,因此我们将所有内容包装在 group 中。同时 address 就像一个子组,所以我们将它包裹在另一个 group 中(您可以查看模板以便更好地理解)!除了 aliases 之外,这里的每个表单控件都是 key,这意味着您可以使用 formBuilder 方法(例如 push)像简单数组一样将值尽可能多地推入其中。

我是这么理解的,希望对大家有帮助。

来自:Anton Moiseev 的书“Angular 使用 Typescript 进行开发,第二版。” :

当您需要以编程方式添加(或删除) 控件表单时,使用 FormArray。它类似于 FormGroup 但有一个 长度变量 FormGroup 表示 整个表单或表单字段的固定子集 FormArray 通常表示 可以扩大或缩小的表单控件集合

例如,您可以使用 FormArray 允许用户输入任意数量的电子邮件。