【问题标题】:Angular2 reactive forms : syncing FormArray with parent FormGroupAngular2 反应形式:将 FormArray 与父 FormGroup 同步
【发布时间】:2017-02-15 11:21:48
【问题描述】:

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

在这一点上,我不知道我的实现是否有问题,或者我是否期待一些我不应该做的事情......无论最终的“问题”是什么,我都会很乐意接受此时的任何输入。

链接到 Plunkerhttps://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 钩子让我能够虚拟地解决问题,但解决方案并不令人满意。出于这个原因,我正在编辑而不是回答我自己的问题,但如果任何模组认为这是一个有效的结论,请务必做你认为合适的事情。

至于我的“解决方案”:不是在 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;

}

通过这样做,根 FormGroup 会在 FormArray 被修改时更新,但会有延迟。例如,如果我在字段 A 中输入“123”,则根 FormGroup 值包含"fieldA":"12"

因此我不满意的“解决方案”:通过在订阅中添加一个虚拟的 setTimeout,根 FormGroup 会完全按照我的意愿更新...除非理想情况下不需要 setTimeout。

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

有没有办法在不求助于 setTimeout 的情况下管理这个?

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

【问题讨论】:

    标签: angular typescript angular2-forms


    【解决方案1】:

    我玩了你的plunker,发现了问题

    在更改大小后分配新的FormArray 时,您单独分配了它,没有正确地将其与父FormGourp 相关联。
    使用 this.form.controls[&lt;controlName&gt;] = new FormControl/ FormArray/ FormGroup; 不会将 parent 属性应用于新控件。
    这就是为什么在更新父字段之一时“刷新”整个表单值之前值不会传播到父级的原因。

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

    我还添加了正确的方法(在我看来)来替换 someArray FormArray 的值。
    使用official documentation 帮助很大。

    希望对你有帮助

    【讨论】:

    • 非常感谢您的意见!鉴于我已经接近我想要的东西,我什至没有尝试弄乱 setControl、setValue 和 patchValue ......我真丢脸 ;) 起初你给的 plunker 没有用,但添加了指向文档,我能够实现我想要的(使用 setControl):plnkr.co/edit/mvkVXN2bsJXkP1O3Zbcl?p=preview
    • 您的解决方案@phl 的唯一问题是,如果您在添加一些值后更新大小,formArray 将被替换而丢失当前值。
    • 我添加了一个具有持久性的解决方案,以防有人想保留当前值plnkr.co/edit/vQ8WAR6cayGr4mC2dqUa?p=preview
    【解决方案2】:

    每当嵌套表单数组更改时,我都会遇到更新父表单组的问题。每当表单数组更改时,尝试设置父属性。希望对您有所帮助。

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

    【讨论】:

      猜你喜欢
      • 2021-07-07
      • 2017-11-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-06-29
      • 2017-12-22
      • 2017-05-08
      相关资源
      最近更新 更多