何时使用 FormGroup 与 FormArray?
Posted
技术标签:
【中文标题】何时使用 FormGroup 与 FormArray?【英文标题】:When to use FormGroup vs. 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')
]);
什么时候应该使用一个而不是另一个?
【问题讨论】:
【参考方案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
、子formGroups
或formArray
FormArray
可以进一步包含formControls
的数组或formGroup
本身。
什么时候应该使用formArray?
请阅读这篇漂亮的post,它解释了formArray
的用法
那个博客中有趣的例子是关于旅行的formGroup
使用formControl
和formArray
的行程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,注意数组在cities
和places
中的用法。
【讨论】:
@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('')
])
);
这里我们有firstName
、lastName
、address
和aliases
所有字段一起是表单组,所以我们将所有内容包装在group
中。同时address
就像一个子组,所以我们把它包装在另一个group
中(你可以看模板更好地理解)!这里的每个表单控件都是key
,除了aliases
,这意味着您可以使用formBuilder
之类的push
等方法像简单数组一样将其值推入任意数量。
这就是我的理解,希望对某人有所帮助。
【讨论】:
以上是关于何时使用 FormGroup 与 FormArray?的主要内容,如果未能解决你的问题,请参考以下文章
formControlName 必须与父 formGroup 指令一起使用
ERROR 错误:formArrayName 必须与父 formGroup 指令一起使用
formGroupName必须与父formGroup指令一起使用