繁体   English   中英

如何将表单值修补到递归嵌套的 Angular 表单?

[英]How to patch form value to a recursive nested Angular Form?

最近,我在 StackOverflow 上提出了以下问题,并收到了一个惊人的回复,导致构建了一个递归嵌套的 Angular 表单: Angular Deeply Nested Reactive Form: Cannot find control with path on nested FormArray 这是作者写的关于同一问题的博客文章

这个递归嵌套的 Angular 表单让我继续构建组FormArrays ,所有这些都有一个group object:

{
  "conjunctor": null,
    "conditions": [
      {
        "variable":   
      }
  "groups": []
}

您可以添加多个conditions实例并进一步嵌套groups如此 StackBlitz所示

本质上,Form 组件已被拆分为多个组件: group-controlcondition-formaction-buttons-bar (发出动作的按钮)。 这种方法可以满足我的一切需求,但是,我在通过这种递归方法修补表单值时遇到了麻烦。

到目前为止,我已经尝试发送 static 语句 object 并将其修补到整个表单本身,以及专门针对groups object。 这是在

应用组件:

(我也在group-control组件中尝试了相同和相似的方法)。 最终我计划使用来自 API 的数据来填充和修补这些值,但现在和测试,使用这个 static 数据

  ngOnInit() {
    const data = {
      statement: {
        groups: [
          {
            conjunctor: "and",
            conditions: [
              {
                variable: "asdf"
              }
            ],
            groups: []
          }
        ]
      }
    };
    this._form.patchValue(data);
    console.log(this._form.value);
  }

是否可以在递归表单上修补statement FormGroup的表单值?

Stackblitz 演示

你的数据没有问题。 这很可能是时间问题。 在您可以修补任何值之前,表单必须是稳定的。 当您在OnInit中执行此操作时,我想您正在构造函数中构建表单。 如果是这样,表单还没有准备好接收任何值。

解决这个问题的最简单方法是使用不舒服的setTimeout 但我想这只是为了测试。 在实际情况下,无论如何,数据可能需要一些时间才能获得。

如果您使用上述setTimeout将其包装起来,则上面的示例将起作用:

ngOnInit() {
  setTimeout(() => {
    const data = {
      statement: {
        groups: [
          {
            conjunctor: "and",
            conditions: [
              {
                variable: "asdf"
              }
            ],
            groups: []
          }
        ]
      }
    };
    this._form.patchValue(data);
    console.log(this._form.value);
  }, 50);
}

下面的动画 gif 显示了 3 个嵌套组中的补丁,最后一个嵌套在第二个组上。

在此处输入图像描述

根据给定数据构建表单

您可以做的一件有趣的事情是根据您拥有的数据自动构建表单。 您可以通过分析进入ControlValueAccessor.writeValue的数据来实现:

if (!value) {
  return;
}
setTimeout(() => {
  if (value && value.conditions && value.conditions.length) {
    this._conditionsFormArray.clear();
    value.conditions.forEach(c => this._addCondition());
  }

  if (value && value.groups && value.groups.length) {
    this._groupsFormArray.clear();
    value.groups.forEach(g => this._addGroup());
  }

  this._form.patchValue(value);
}, 50);

也许你已经注意到上面的setTimeout ,它的存在是因为我们在表单创建方法中有另一个 setTimeout(在OnInit上调用),它在表单创建后向表单添加条件,而条件的创建本身是在setTimeout中. 因此,我们必须等待它运行,否则this._conditionsFormArray.clear(); 不会有任何影响 => 运行时不会创建任何条件。

private _createFormGroup() {
  this._form = this._fb.group({
    conjunctor: null,
    conditions: this._fb.array([]),
    groups: this._fb.array([])
  });

  // add one condition on the next tick, after the form creation
  setTimeout(() => this._addCondition());
}

然后通过一些调整,我们可以得到以下结果(下面的 gif 是基于另一个Stackblitz 演示):

在此处输入图像描述

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM