如何将表单组绑定到 Angular 中嵌套的动态创建的组件

Posted

技术标签:

【中文标题】如何将表单组绑定到 Angular 中嵌套的动态创建的组件【英文标题】:How to bind form group to nested dynamically created components in Angular 【发布时间】:2022-01-21 08:37:51 【问题描述】:

在我的 Angular 12 应用程序中,我有这种类型的层次结构:

- app.component
-- Parent component with form (reactive)
--- Component that creates the dynamic components
---- Dynamic component

我的 formBuilder 表单如下所示:

    form = this.fb.group(
        baseLevelControl: ["base control"],
        groupOfGroups: [this.fb.group(
            innerGroup1: this.fb.group(
                dummy1Control1: "control 1 from inner group 1",
                dummy1Control2: "control 2 from inner group 1",
            ),
            innerGroup2: this.fb.group(
                dummy2Control1: "control 1 from inner group 2",
                dummy2Control2: "control 2 from inner group 2",
            ),
        )]
    );

我的动态组件只需要知道 groupOfGroups 而不是整个表单,因为它将在许多地方使用不同类型的表单。

当我在动态组件中设置时

<div [formGroup]="innerForm">

我得到一个不与父表单通信的独立表单。 如果我使用

<div formGroupName="innerForm">

我收到formGroupName must be used with a parent formGroup directive 的错误

如何正确绑定 groupOfGroups?

我已创建 this stackblitz project 来模拟该问题,我们将不胜感激任何帮助

【问题讨论】:

我希望动态组件独立于父表单,只知道 groupOfGroups 子表单组。例如,使用 ControlValueAccessor 代替 ControlContainer。也许我弄错了,我不确定 @AkiS 当您想将子组件的 formGroup 绑定到父组件表单时,它根本不会是独立的,是的,您可以独立处理子组件逻辑,但不能说任何组是独立的、分配的和与父 formGroup 分组。 好吧,也许我没有正确描述它。 Ofc 它将属于父窗体。我想要的是只从我的动态组件中引用特定的表单组。在另一个用例中,这个动态组件可以以不同的结构形式使用,并且 groupOfGroups 可以嵌套多个级别。但我的主要问题是我无法使动态的形式以一种或另一种方式链接到父级 【参考方案1】:

您可以在子组件中注入ControlContainer 以访问父组件表单组。

https://stackblitz.com/edit/angular-ivy-slgmo9

在您的子组件 dynamic1.component.ts 中,注入 ControlContainer 并将父表单组分配给子组件的 FormGroup 属性。这将使您能够从父组件访问父 FormGroup

@Component(
  selector: 'app-dynamic1',
  templateUrl: './dynamic1.component.html',
  styleUrls: ['./dynamic1.component.scss'],
)
export class Dynamic1Component implements OnInit 
  public formGroup: FormGroup;

  constructor(private _parentContainer: ControlContainer) 

  ngOnInit(): void 
    this.formGroup = this._parentContainer.control as FormGroup;
  

更新您的 dynamic1.component.html 以使用此表单组。

<div *ngIf="formGroup" [formGroup]="formGroup">
  <div formGroupName="innerGroup1">
    <p>dummy controls for group 1</p>
    <input formControlName="dummy1Control1" />
    <input formControlName="dummy1Control2" />
  </div>
  <div formGroupName="innerGroup2">
    <p>dummy controls for group 2</p>
    <input formControlName="dummy2Control1" />
    <input formControlName="dummy2Control2" />
  </div>
</div>

在您的 level1.component.ts 中更新 FormGroup。您最初将 groupOfGroups 作为数组。这不是必需的,您只需为其分配一个 FormGroup 即可。

@Component(
  selector: 'app-level1',
  templateUrl: './level1.component.html',
  styleUrls: ['./level1.component.scss'],
)
export class Level1Component implements OnInit 
  form = this.fb.group(
    baseLevelControl: ['base control'],
    groupOfGroups: this.fb.group(
      innerGroup1: this.fb.group(
        dummy1Control1: 'control 1 from inner group 1',
        dummy1Control2: 'control 2 from inner group 1',
      ),
      innerGroup2: this.fb.group(
        dummy2Control1: 'control 1 from inner group 2',
        dummy2Control2: 'control 2 from inner group 2',
      ),
    ),
  );

  // OTHER STUFF....


你的level1.component.html 模板看起来像......

<h1>Level 1</h1>
<div [formGroup]="form">
  <label for="baseControl">Base Control Value:</label>
  <input name="baseControl" formControlName="baseLevelControl" type="text" />
  <div formGroupName="groupOfGroups">
    <h3>Dynamic 2</h3>
    <app-dynamic1></app-dynamic1>
  </div>
  <div>
    <button type="button" (click)="onSubmit()">Submit</button>
  </div>
</div>
https://jenniferwadella.com/blog/angular-control-container

【讨论】:

这确实有效。我的代码中有一个错字(groupOfGroups: [this.fb.group....] 上的一个额外 [])导致 groupOfGroups FormGroup 被视为 FormControl。无论如何,我会将其标记为答案,但是我有兴趣看到使用 ControlValueAccessor 而不是 ControlContainer 的解决方案。非常感谢

以上是关于如何将表单组绑定到 Angular 中嵌套的动态创建的组件的主要内容,如果未能解决你的问题,请参考以下文章

Angular 2 - 单元测试绑定到嵌套的自定义表单控件

在新的 Angular 2 表单中将 NgModel 绑定到 FormControl

如何将数据绑定到 Angular 2 中的多个嵌套组件?

如何删除 Angular 表单组中的特定错误

如何在 AngularJS 表单中嵌套 Angular 2+ 表单?

动态嵌套表单控件Angular 2