Angular2反应形式:将FormArray与父FormGroup同步

phl*_*phl 10 typescript angular2-forms angular

我正在使用FormArrays来处理可变长度的对象数组.虽然我当前的实现主要起作用,但在验证方面我遇到了问题,因为对FormArray所做的任何更改都不会传播到其"父"FormGroup ...或者至少不会自动更新FormGroup的值可以更新,通过更改由所述FormGroup管理的另一个控件的值.

在这一点上,我无法判断我的实现是否有问题,或者我是否期待我不应该做的事情......无论"问题"到底是什么,我都很乐意接受任何意见.这点.

链接到Plunker:https://plnkr.co/edit/PLslyJo1YOszGwTpujyx (Angular版本是2.0.1)

Plunker app.ts顶部的评论详细说明了重现问题的步骤(或者对我来说有什么问题).

当链接到Plunker时SO要求一些代码,这里是与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();
  }
}
Run Code Online (Sandbox Code Playgroud)

这是在Plunker中说明的,但我在这里可能会提到订阅FormArray的valueChanges似乎没有帮助(或者我在订阅中没有做正确的事情):

this.form.controls['someArray'].valueChanges.subscribe((data) => this.form.updateValueAndValidity());
Run Code Online (Sandbox Code Playgroud)

感谢任何人在ch :)

编辑(2016-10-11):玩弄valueChanges钩子更能让我实际上解决问题,但解决方案不尽如人意.出于这个原因,我正在编辑而不是回答我自己的问题,但如果任何mod认为这是一个有效的结论,请务必做你认为合适的事情.

至于我的"解决方案":不是订阅valueChangesFormArray或根FormGroup级别,我几乎可以通过订阅valueChanges组成FormArray的每个FormGroup 的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;
Run Code Online (Sandbox Code Playgroud)

}

通过这样做,根FormGroup在修改FormArray时更新,但有滞后.例如,如果我在字段A中输入"123",则根FormGroup值包含"fieldA":"12".

因此,我不满意的"解决方案":通过在订阅中添加一个虚拟的setTimeout,根FormGroup更新完全符合我的要求...除了理想情况下不需要setTimeout.

formGroup.valueChanges.subscribe((data) => setTimeout(()=>this.form.updateValueAndValidity(), 1);
Run Code Online (Sandbox Code Playgroud)

有没有办法在不诉诸setTimeout的情况下管理它?

更新的Plunker:https://plnkr.co/edit/7mbTNPHjRhlU3ostf3av

Ami*_*ugi 6

我和你的羽毛球玩了一些,发现了问题

如果FormArray在更改大小后分配了新大小,则单独分配它,而不是将其正确地与父级相关联FormGourp.
使用this.form.controls[<controlName>] = new FormControl/ FormArray/ FormGroup;不会将parent属性应用于新控件.
这就是为什么在更新其中一个父字段时,"刷新"整个表单值之前,值不会传播到父级.

你可以在plunker中看到,我console.log为你提供了一些更好的理解.

我还添加了正确的方法(在我看来)来替换someArrayFormArray 的值.
使用官方文档有很多帮助.

希望这可以帮助

  • 非常感谢您的投入!鉴于我接近我正在寻找的东西,我甚至没有尝试使用setControl,setValue和patchValue ......对我感到羞耻;)首先,你提供的plunker没有工作,但添加了链接到文档,我能够实现我想要的(使用setControl):https://plnkr.co/edit/mvkVXN2bsJXkP1O3Zbcl?p = preview (2认同)