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

How to bind form group to nested dynamically created components in Angular

在我的 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 来模拟这个问题,任何帮助将不胜感激

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

在您的子 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>