首页 > 解决方案 > 在 ngAfterViewInit 之后 createEmbeddedView 进入内容投影

问题描述

我有一个设置,parent.component其中一些复杂的动态模板在一些命名ng-template元素中解析。然后我想在页面上以动态顺序插入这些,我在ngAfterViewInitusing中执行此操作createEmbeddedView。这需要一个setTimeout,否则我会得到一个 Angular ExpressionChangedAfterItHasBeenCheckedError

这本身看起来很混乱,但现在我正在尝试将这些动态元素内容投影到子组件中。元素不出现。我应该如何使用 Angular 的生命周期和更改检测才能正确执行此操作?

另一个会使示例复杂化的怪癖:在我的实际实现中,子组件的ng-content位置隐藏在ngIf指令后面。如果将投影的动态内容初始化为 on,则不会出现,但如果将其从 off 切换为 on,则会出现,因此子组件正在以某种方式接收和保存投影。

例子

parent.component.html

<ng-template #insertedElement1>
  ...
</ng-template>
<ng-template #insertedElement2>
  ...
</ng-template>
<ng-template #insertedElement3>
  ...
</ng-template>

<child-component>
  <span #insertionPoint></span>
</child-component>

parent.component.ts

...
@ViewChild('insertionPoint', { static: false, read: ViewContainerRef })
insertionPoint: ViewContainerRef;

// static false because these elements have structural logic within them
@ViewChild('insertedElement1', { static: false })
insertedElement1: TemplateRef<any>;
@ViewChild('insertedElement2', { static: false })
insertedElement2: TemplateRef<any>;
@ViewChild('insertedElement3', { static: false })
insertedElement3: TemplateRef<any>;

// ngAfterViewInit to let the structural logic complete
ngAfterViewInit() {
  // After timeout or I get ExpressionChangedAfterItHasBeenCheckedError
  setTimeout(() => {
    // This array is fixed for this example, but would be dynamic
    [
      "insertedElement3"
      "insertedElement1"
      "insertedElement2"
    ].forEach(element => {
      this.insertionPoint.createEmbeddedView(this[element]);
    });
  });
}
...

标签: angularangular-templateangular-lifecycle-hooks

解决方案


推荐阅读