我在这里没有看到一个解决方案可以最大程度地使用react形式完全回答问题,所以这是我的解决方案。
概括
这是详细解释的要点以及 StackBlitz 示例。
- 使用
FormArray
该复选框并初始化形式。
valueChanges
当您希望表单显示某些内容但在组件中存储其他内容时,observable 是完美的选择。将true
/false
值映射到此处所需的值。
- 过滤掉
false
提交时的值。
- 取消订阅
valueChanges
observable。
详细说明
使用 FormArray 定义表单
正如在标记为正确的答案中已经提到的那样。FormArray
在您希望以数组形式获取数据的情况下,这是一种可行的方法。因此,您需要做的第一件事就是创建表单。
checkboxGroup: FormGroup;
checkboxes = [{
name: 'Value 1',
value: 'value-1'
}, {
name: 'Value 2',
value: 'value-2'
}];
this.checkboxGroup = this.fb.group({
checkboxes: this.fb.array(this.checkboxes.map(x => false))
});
这只会将所有复选框的初始值设置为false
。
接下来,我们需要在模板中注册这些表单变量并遍历checkboxes
数组(不是FormArray
复选框数据)以在模板中显示它们。
<form [formGroup]="checkboxGroup">
<ng-container *ngFor="let checkbox of checkboxes; let i = index" formArrayName="checkboxes">
<input type="checkbox" [formControlName]="i" />{{checkbox.name}}
</ng-container>
</form>
使用 valueChanges 可观察
这是我在这里给出的任何答案中都没有提到的部分。在这种情况下,我们希望显示所述数据但将其存储为其他内容,valueChanges
可观察对象非常有用。使用valueChanges
,我们可以观察到在变化checkboxes
,然后map
在true
/false
从接收到的值FormArray
,以所期望的数据。请注意,这不会更改复选框的选择,因为传递给复选框的任何真实值都会将其标记为已选中,反之亦然。
subscription: Subscription;
const checkboxControl = (this.checkboxGroup.controls.checkboxes as FormArray);
this.subscription = checkboxControl.valueChanges.subscribe(checkbox => {
checkboxControl.setValue(
checkboxControl.value.map((value, i) => value ? this.checkboxes[i].value : false),
{ emitEvent: false }
);
});
这基本上将FormArray
值映射到原始checkboxes
数组,并value
在复选框标记为 的情况下true
返回 ,否则返回false
。在emitEvent: false
这里很重要,因为设置FormArray
没有它的值将导致 valueChanges
发出一个创建无限循环的事件。通过设置emitEvent
为false
,我们确保在valueChanges
此处设置值时 observable 不会发出。
过滤掉错误值
我们不能直接过滤 中的false
值,FormArray
因为这样做会弄乱模板,因为它们绑定到复选框。所以最好的解决方案是false
在提交过程中过滤掉这些值。使用扩展运算符来执行此操作。
submit() {
const checkboxControl = (this.checkboxGroup.controls.checkboxes as FormArray);
const formValue = {
...this.checkboxGroup.value,
checkboxes: checkboxControl.value.filter(value => !!value)
}
// Submit formValue here instead of this.checkboxGroup.value as it contains the filtered data
}
这基本上过滤掉falsy从值checkboxes
。
取消订阅 valueChanges
最后别忘了退订 valueChanges
ngOnDestroy() {
this.subscription.unsubscribe();
}
注意:有一种特殊情况,值不能设置为FormArray
in valueChanges
,即如果复选框值设置为 number 0
。这将使该复选框看起来无法选中,因为选择该复选框会将 设置FormControl
为数字0
(假值),因此保持未选中状态。最好不要将数字0
用作值,但如果需要,您必须有条件地设置0
为某个真实值,例如字符串'0'
或只是普通值,true
然后在提交时将其转换回数字0
。
StackBlitz 也有代码用于何时您希望将默认值传递给复选框,以便在 UI 中将它们标记为已选中。