簡體   English   中英

Angular2反應形式:將FormArray與父FormGroup同步

[英]Angular2 reactive forms : syncing FormArray with parent FormGroup

我正在使用FormArrays處理可變長度的對象數組。 盡管我目前的實現方式大部分都能正常工作,但是在驗證方面卻遇到了問題,因為對FormArray所做的任何更改都不會傳播到其“父級” FormGroup ...或至少不會自動傳播。FormGroup的值可以更新,通過更改由所述FormGroup管理的另一個控件的值。

在這一點上,我無法確定我的實現是否存在問題,或者我期望我不應該發生什么……無論最終“問題”是什么,我都會樂意接受這點。

鏈接到Plunkerhttps : //plnkr.co/edit/PLslyJo1YOszGwTpujyx (角版本為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認為這是一個有效的結論,請執行您認為足夠的事情。

至於我的“解決方案”:我不需要訂閱FormArray或root FormGroup級別的valueChanges ,而是可以通過訂閱組成FormArray的每個FormGroup的valueChanges幾乎實現我想要的:

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,但會有滯后。 例如,如果我在字段A中輸入“ 123”,則FormGroup的根值包含"fieldA":"12"

因此,我的解決方案不盡如人意:通過在訂閱中添加一個虛擬setTimeout,根FormGroup完全按照我想要的方式進行更新...除非理想情況下不需要setTimeout。

formGroup.valueChanges.subscribe((data) => setTimeout(()=>this.form.updateValueAndValidity(), 1);

有什么方法可以解決此問題而無需訴諸setTimeout?

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

我和你的小矮人玩了一下,發現了問題所在

更改大小后分配新的FormArray時,您是單獨分配的,未將其正確關聯到父FormGourp
使用this.form.controls[<controlName>] = new FormControl/ FormArray/ FormGroup; 不會將parent屬性應用於新控件。
這就是為什么在更新父字段之一時“刷新”整個表單值之前,值不會傳播到父字段的原因。

您可以在插件中看到,我添加了一些console.log以便您更好地理解。

我還添加了正確的方法(我認為)來替換someArray FormArray的值。
使用官方文檔有很大幫助。

希望這可以幫助

每當嵌套表單數組發生更改時,我都會更新父表單組。 每當表單數組更改時,嘗試設置父屬性。 希望能幫助到你。

addItem(): void {
    let fa = <FormArray>this.formGroup.get(this.formProperty)
    let fb = this.CreateNewRow(this.schema);
    fb.setParent(fa);
    fa.controls.push(fb);
  }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM