Angular2 反应形式:将 FormArray 与父 FormGroup 同步
Angular2 reactive forms : syncing FormArray with parent FormGroup
我正在使用 FormArrays 来处理可变长度的对象数组。虽然我当前的实现大部分都有效,但在验证方面我遇到了问题,因为对我的 FormArray 所做的任何更改都不会传播到它的 "parent" FormGroup ......或者至少不会自动传播 FormGroup 可以通过更改由所述 FormGroup 管理的另一个控件的值来更新。
在这一点上,我无法判断我的实现是否有问题,或者我是否期待一些我不应该期待的事情......无论 "problem" 最后是什么,我此时很乐意接受任何意见。
Link 到 Plunker : https://plnkr.co/edit/PLslyJo1YOszGwTpujyx
(Angular 版本为 2.0.1)
Plunker app.ts 顶部的评论详细说明了重现问题的步骤(或者无论如何对我来说是什么问题)。
由于 SO 在链接到 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 认为这是一个有效的结论,请务必做你认为足够的事情。
至于我的 "solution" :不是在 FormArray 或根 FormGroup 级别订阅 valueChanges
,我几乎可以通过订阅每个 FormGroup 的 valueChanges
observable 来实现我想要的组成 FormArray :
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;
}
通过这样做,根 FormGroup 在 FormArray 被 mod 化时更新,但有一个滞后。例如,如果我在字段 A 中输入“123”,则根 FormGroup 值包含 "fieldA":"12"
。
因此我不满意 "solution" :通过在订阅中添加一个虚拟的 setTimeout,根 FormGroup 完全按照我想要的方式更新......除了理想情况下不需要 setTimeout。
formGroup.valueChanges.subscribe((data) => setTimeout(()=>this.form.updateValueAndValidity(), 1);
有没有什么方法可以在不诉诸 setTimeout 的情况下进行管理?
更新的 Plunker :https://plnkr.co/edit/7mbTNPHjRhlU3ostf3av
我玩了一下你的plunker,发现了问题
当您在更改大小后分配新的 FormArray
时,您是单独分配它,没有正确地将它与父 FormGourp
相关联。
使用 this.form.controls[<controlName>] = new FormControl/ FormArray/ FormGroup;
不会将 parent
属性 应用于新控件。
这就是为什么在更新父字段之一时,直到 "refreshed" 整个表单值才将值传播到父字段。
你可以在plunker中看到,我添加了一些console.log
,以便你更好地理解。
我还添加了正确的方法(在我看来)来替换 someArray
FormArray 的值。
使用 official documentation 帮助很大。
希望对您有所帮助
每当嵌套表单数组发生变化时,我都会遇到更新父表单组的问题。每当表单数组更改时,尝试设置父级 属性。希望对你有帮助。
addItem(): void {
let fa = <FormArray>this.formGroup.get(this.formProperty)
let fb = this.CreateNewRow(this.schema);
fb.setParent(fa);
fa.controls.push(fb);
}
我正在使用 FormArrays 来处理可变长度的对象数组。虽然我当前的实现大部分都有效,但在验证方面我遇到了问题,因为对我的 FormArray 所做的任何更改都不会传播到它的 "parent" FormGroup ......或者至少不会自动传播 FormGroup 可以通过更改由所述 FormGroup 管理的另一个控件的值来更新。
在这一点上,我无法判断我的实现是否有问题,或者我是否期待一些我不应该期待的事情......无论 "problem" 最后是什么,我此时很乐意接受任何意见。
Link 到 Plunker : https://plnkr.co/edit/PLslyJo1YOszGwTpujyx (Angular 版本为 2.0.1)
Plunker app.ts 顶部的评论详细说明了重现问题的步骤(或者无论如何对我来说是什么问题)。
由于 SO 在链接到 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 认为这是一个有效的结论,请务必做你认为足够的事情。
至于我的 "solution" :不是在 FormArray 或根 FormGroup 级别订阅 valueChanges
,我几乎可以通过订阅每个 FormGroup 的 valueChanges
observable 来实现我想要的组成 FormArray :
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;
}
通过这样做,根 FormGroup 在 FormArray 被 mod 化时更新,但有一个滞后。例如,如果我在字段 A 中输入“123”,则根 FormGroup 值包含 "fieldA":"12"
。
因此我不满意 "solution" :通过在订阅中添加一个虚拟的 setTimeout,根 FormGroup 完全按照我想要的方式更新......除了理想情况下不需要 setTimeout。
formGroup.valueChanges.subscribe((data) => setTimeout(()=>this.form.updateValueAndValidity(), 1);
有没有什么方法可以在不诉诸 setTimeout 的情况下进行管理?
更新的 Plunker :https://plnkr.co/edit/7mbTNPHjRhlU3ostf3av
我玩了一下你的plunker,发现了问题
当您在更改大小后分配新的 FormArray
时,您是单独分配它,没有正确地将它与父 FormGourp
相关联。
使用 this.form.controls[<controlName>] = new FormControl/ FormArray/ FormGroup;
不会将 parent
属性 应用于新控件。
这就是为什么在更新父字段之一时,直到 "refreshed" 整个表单值才将值传播到父字段。
你可以在plunker中看到,我添加了一些console.log
,以便你更好地理解。
我还添加了正确的方法(在我看来)来替换 someArray
FormArray 的值。
使用 official documentation 帮助很大。
希望对您有所帮助
每当嵌套表单数组发生变化时,我都会遇到更新父表单组的问题。每当表单数组更改时,尝试设置父级 属性。希望对你有帮助。
addItem(): void {
let fa = <FormArray>this.formGroup.get(this.formProperty)
let fb = this.CreateNewRow(this.schema);
fb.setParent(fa);
fa.controls.push(fb);
}