我正在使用FormArrays来处理可变长度的对象数组。虽然我当前的实现主要起作用,但在验证方面我遇到了问题,因为对我的FormArray所做的任何更改都不会传播到它的" parent" FormGroup ...或至少不自动通过更改由所述FormGroup管理的另一个控件的值,可以更新FormGroup 的值。
此时,我无法判断我的实施是否有问题,或者我是否期待某些事情我不应该......不管是什么问题""问题&#34 ;最后,我很乐意接受任何意见。
链接到Plunker :https://plnkr.co/edit/PLslyJo1YOszGwTpujyx (Angular版本是2.0.1)
Plunker app.ts顶部的评论详细说明了重现问题的步骤(或者对我来说有什么问题)。
当链接到Plunker时要求一些代码,这里是与FormGroup和FormArray的定义有关的行
this.form = this.fb.group({
"size":[0, Validators.required],
"someArray": this.fb.array(this.initFormArray(0), Validators.required),
"someOtherField":[null]
});
initFormArray(size:number):FormGroup[]{
let newFormArray:FormGroup[] = [] ;
for(let i = 0 ; i < size ; i++){
newFormArray.push(this.fb.group({
fieldA: [null, Validators.required],
fieldB: [null, Validators.required]
}));
}
return newFormArray;
}
updateFormArray(value:string){
let newSize:number = parseInt(value) ;
if(newSize >= 0){
this.form.controls["someArray"] = this.fb.array(this.initFormArray(newSize))
this.form.updateValueAndValidity();
}
}
这在Plunker中有说明,但我在这里可能会提到订阅FormArray的valueChanges似乎没有帮助(或者我在订阅中没有做正确的事情):
this.form.controls['someArray'].valueChanges.subscribe((data) => this.form.updateValueAndValidity());
感谢所有人在讨论:)
编辑(2016-10-11):使用valueChanges
钩子更多地允许我实际解决问题,但解决方案不尽如人意。出于这个原因,我编辑而不是回答我自己的问题,但如果任何mod认为这是一个有效的结论,请务必做你认为合适的事情。
至于我的解决方案&#34; :而不是在FormArray或根FormGroup级别订阅valueChanges
,我几乎可以通过订阅组成FormArray的每个FormGroup的valueChanges
observable来实现我想要的:
initFormArray(size:number):FormGroup[]{
let newFormArray:FormGroup[] = [] ;
for(let i = 0 ; i < size ; i++){
let formGroup = this.fb.group({
fieldA: [null, Validators.required],
fieldB: [null, Validators.required]
}) ;
formGroup.valueChanges.subscribe((data) => this.form.updateValueAndValidity());
newFormArray.push(formGroup);
}
return newFormArray;
}
通过这样做,修改FormArray时会更新根FormGroup,但会有滞后。例如,如果我输入&#34; 123&#34;在字段A中,根FormGroup值包含"fieldA":"12"
。
因此我不满意&#34;解决方案&#34; :通过在订阅中添加一个虚拟的setTimeout,根FormGroup更新完全按照我的意愿...除了理想情况下不需要setTimeout。
formGroup.valueChanges.subscribe((data) => setTimeout(()=>this.form.updateValueAndValidity(), 1);
有没有办法在不诉诸setTimeout的情况下管理它?
更新的Plunker:https://plnkr.co/edit/7mbTNPHjRhlU3ostf3av
答案 0 :(得分:6)
我和你的羽毛球玩了一些,发现了问题
如果您在更改其大小后指定了新的FormArray
,则单独分配,而不是将其正确地与父FormGourp
相关联。
使用this.form.controls[<controlName>] = new FormControl/ FormArray/ FormGroup;
不会将parent
属性应用于新控件
这就是为什么在更新其中一个父字段时,“刷新”整个表单值之前,值不会传播到父级。
您可以在plunker中看到,我添加了一些console.log
供您更好地理解。
我还添加了正确的方法(在我看来)来替换someArray
FormArray的值。
使用official documentation帮助了很多。
希望这有帮助
答案 1 :(得分:0)
每当嵌套表单数组发生更改时,我都会遇到更新父表单组的相同问题。每当表单数组更改时,尝试设置父属性。希望对您有所帮助。
addItem(): void {
let fa = <FormArray>this.formGroup.get(this.formProperty)
let fb = this.CreateNewRow(this.schema);
fb.setParent(fa);
fa.controls.push(fb);
}