何时使用FormGroup与FormArray?


91

FormGroup

一个FormGroup将每个子FormControl的值聚合到一个对象中,并以每个控件名称作为键。

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

FormArray

FormArray聚集每个子FormControl的值到一个数组。

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

什么时候应该使用另一个?

Answers:


122

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>

这是定义和处理特殊请求的组件类:

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更大的灵活性,因为与使用FormGroup的“ addControl”,“ removeControl”,“ setValue”等相比,使用“ push”,“ insert”和“ removeAt”更容易操作FormControl。FormArray方法可确保控件是在表单的层次结构中正确跟踪。

希望这可以帮助。


4
如果您要编辑表单怎么办?您如何迭代和添加控件?
ctilley79 '17

1
您如何将其重构为组件?
贾斯汀

是否可以将具有key:value的对象而不只是值添加到表单数组中?
安东尼

我们如何设置表单标签名称?窗体控件初始化时,有什么选项可以设置?由于表单是动态的,我们无法设置其值。
Krishnadas PC

29

为了创建反应形式,FormGroup必须有父母。这FormGroup还可以含有formControls,儿童formGroupsformArray

FormArray可以进一步包含formControlsformGroup本身的数组。

我们什么时候应该使用formArray?

请阅读这篇漂亮的文章,其中解释了formArray

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

formGroup使用formControl和的旅行结构formArray如下所示:

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旅行的。


简短而甜美的解释。
Kanchan

令人惊讶的解释
Taoufik Jabbari

好兄弟
贾尔帕

@scopchanov文本可能没有太多解释,但是表单结构表示确实给出了一些想法。让我知道是否有什么可以改善答案的方法:)
阿米特·奇加达尼

好吧,如果有人说“解释”,那么我希望能确切地看到。尽我所能,根据SO的定义,您的答案非常接近“仅链接的答案”,因为就在正确的位置,即何时应该使用formArray?,提供了指向博客文章的链接,但没有引用其中的重要部分。您确实已经发布了一些代码,但是仍然没有任何解释。如果您引用了本博文中的两个规则,那将带来巨大的变化。
scopchanov

5

来自:安东·莫谢耶夫(Anton Moiseev)书“带打字稿的角度开发,第二版”。:

当您需要以编程方式表单添加(或删除)控件时,请使用FormArray。它与FormGroup相似,但是具有一个length变量。而FormGroup代表整个表单或表单的字段的固定子集FormArray通常代表一个可以放大或缩小表单控件的集合

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


0

从角度文档中您可以看到

FormArray是用于管理任意数量的未命名控件的FormGroup的替代方法。与表单组实例一样,您可以动态地从表单数组实例中插入和删除控件,并且表单数组实例的值和验证状态是从其子控件中计算出来的。但是,您不需要按名称为每个控件定义键,因此,如果您事先不知道子值的数量,那么这是一个不错的选择。

让我向您展示他们的示例,并尝试解释我对此的理解。你可以在这里看到源

想象一个女巫有以下领域

  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(您可以查看模板以获得更好的理解)!这里的每个窗体控件都key除外aliases,这意味着您可以使用formBuilder诸如之类的简单数组将其值尽可能多地推入到简单数组中push

这就是我的理解方式,希望对您有所帮助。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.