【问题标题】:When to use FormGroup vs. FormArray?何时使用 FormGroup 与 FormArray?
【发布时间】:2017-05-08 10:05:41
【问题描述】:

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')
]);

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

【问题讨论】:

    标签: angular angular2-forms angular-reactive-forms


    【解决方案1】:

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

    希望这会有所帮助。

    【讨论】:

    • 如果您尝试编辑表单怎么办?如何迭代和添加控件?
    • 你会如何将它重构为组件?
    • 是否可以将带有 key:value 的对象添加到表单数组中,而不仅仅是值?
    • 如何设置表单标签名称?初始化表单控件时是否有任何选项可以设置?由于表单是动态的,我们无法设置它的值。
    【解决方案2】:

    为了创建响应式表单,必须有一个父级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 中的用法。

    【讨论】:

    • @scopchanov 可能对文字没有太多解释,但表单结构表示确实提供了一些思路。让我知道我们是否可以添加任何内容来改进答案:)
    • 好吧,如果有人说“解释”,那么我希望能看到。恕我直言,根据 SO 定义,您的答案非常接近于“仅链接答案”,因为就在它到达重点的地方,即 我们何时应该使用 formArray?,一个指向提供了一篇博文,但未引用其中的任何重要部分。您确实发布了一些代码,但再次没有任何解释。如果您引用了这篇博文中的两条规则,那将会产生巨大的影响。
    • @scopchanov 当然,当我有时间补充时,我会改进这个答案。
    【解决方案3】:

    来自:Anton Moiseev 的书“Angular Development with Typescript, Second Edition”。 :

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

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

    【讨论】:

      【解决方案4】:

      从 Angular 文档中你可以看到

      FormArray 是 FormGroup 的替代方案,用于管理任意数量的 未命名的控件。与表单组实例一样,您可以动态地 从表单数组实例中插入和删除控件,以及表单 数组实例值和验证状态是从它的 子控件。但是,您不需要为每个 按名称控制,所以如果您不知道 预先设置子值的数量。

      让我向您展示他们的示例,并尝试解释我是如何理解这一点的。可以看源码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 中(你可以看模板更好地理解)!这里的每个表单控件都是key,除了aliases,这意味着您可以使用formBuilder 之类的push 等方法像简单数组一样将其值推入任意数量。

      这就是我的理解,希望对某人有所帮助。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-08-14
        • 2018-09-03
        • 2021-02-02
        • 1970-01-01
        • 2020-02-20
        • 1970-01-01
        • 2017-06-09
        • 2018-10-03
        相关资源
        最近更新 更多