在 embeddedView 中访问容器组件的 FormGroupDirective

Access FormGroupDirective of container component inside an embeddedView

越来越多地了解反应式表单的实际工作原理,我仍然不时地试图弄清楚实际发生了什么以及如何使特定场景发生。例如,我目前正在尝试创建一个可重用组件并通过嵌入式视图添加输入字段。

不幸的是,我总是收到关于我的 formControlName 必须如何与父 formGroup 指令一起使用的错误。为了防止在投影内容之前发生此错误,我将内容包装在一个 ng-template 中,并将其 instanciaqtion 移动到显示投影内容的子组件。但它仍然抱怨没有 form group 指令存在。

因此,我的问题是:如何根据注入器处理 ng-content 或 ng-template,您能否指出我做错的正确方向?

我还尝试创建一个指令,将其放在 ng-container 上并通过 providers: [{providers: ControlContainer, useExisting: FormGroupDirective}] 注入 existingFormGroup 指令。运气不好。

为了更好地了解实际情况,我创建了一个 stackblitz:https://stackblitz.com/edit/angular-uuvbrg

非常感谢您的时间和精力!

对于动态创建的视图Angular区分两种类型:

  • 声明视图 - 声明模板的视图

  • 插入视图 - 插入模板的视图

这里的主要规则是 上下文继承自 声明视图树,而不是插入视图树。

这意味着有一个像这样的模板:

<app-form-list-item>
  <ng-template #someChild>
    <input type="text" formControlName="myUsername">
  </ng-template>
</app-form-list-item>

我们应该确保 formControlName 指令可以找到 ControlContainer 从这个模板开始爬树的依赖关系,而不是 app-form-list-item 中的模板。

将任何带有 ControlContainer 提供程序的指令放在 form-list-item.component.html 中无济于事,因为 formControlName 是在父组件中声明的。

一种解决方法,在这里可能可行并且不需要在父组件中编写代码,是在您的 FormListItemComponent:

上提供 ControlContainer

表单列表-item.component.html

<form #ngForm="ngForm" ...

表单列表-item.component.ts

@Component({
  ...
  providers: [
    {
      provide: ControlContainer,
      useFactory: (comp: FormListItemComponent) => comp.ngForm,
      deps: [FormListItemComponent] 
    }
  ]
})
export class FormListItemComponent implements AfterContentInit {
  ...
  @ViewChild('ngForm') ngForm: FormGroupDirective;

它将导致

<app-form-list-item>    <=== ControlContainer that points to inner FormGroupDirective
 /\
 ||   <ng-template #someChild>
 ||
 ||     <input type="text" formControlName="myUsername">

而且只有将内容包装在模板中才会起作用,否则 ControlContainer 将指向空的 FormGroupDirective

Forked Stackblitz

另请参阅: