ComponentHostDirective

ComponentHostDirective

我正在构建一个小型引用应用程序,以了解如何在一个组件中动态注入组件以查看页面上的内容。我得到一个指向viewContainerRef对象的错误。
这个组件应该在视图中显示注入的组件的内容,但它抛出了一个错误:
angular -  Angular 动态分量注入(inject)错误-LMLPHP
以下是引发错误的StatsComponent:

export class StatsComponent implements AfterViewInit, OnDestroy {
  @Input() dynComp: DynamicComponent;
  @ViewChild(ComponentHostDirective) appComponentHost: ComponentHostDirective;
  componentRef: ComponentRef<any>;

  constructor(private componentFactoryResolver: ComponentFactoryResolver) { }

  ngAfterViewInit() {
    this.loadComponent();
  }

  ngOnDestroy() {
    this.componentRef.destroy();
  }

  loadComponent() {
    console.log('inside stats component: ', this.dynComp);
    const comp = this.dynComp;
    const componentFactory = this.componentFactoryResolver.resolveComponentFactory(comp.component);
    console.log('host: ', this.appComponentHost);  // <-- this is undefined

    const viewContainerRef = this.appComponentHost.viewContainerRef;
    viewContainerRef.clear();

    this.componentRef = viewContainerRef.createComponent(componentFactory);
    (<DynamicComponent>this.componentRef.instance).data = comp.data;
  }

}

我有一个工作演示和一个项目。
为什么没有引用容器?
[更新]:现在可以了!去我的演示和github项目看看它的实际效果。

最佳答案

Angular无法识别模板中的@ViewChild(ComponentHostDirective),因为您没有将ComponentHostDirective指令包含到用于编译StatsComponent的指令列表中:
要了解Angular用来编译Angular模板的指令,请看这个答案Angular 2 Use component from another module(参见图)
我知道你已经在ComponentHostDirective内声明了AppModule。但是StatsComponent是在HomeModule中声明的,这个模块对ComponentHostDirective一无所知。我们必须在HomeModule中声明或导入此指令。
如果我们在ComponentHostDirective中声明HomeModule,就会得到错误
类型componenthostdirective是两个模块声明的一部分:
应用模块和家庭模块!
SharedModule救援:
src/app/shared/shared.module.ts文件

@NgModule({
  imports: [
    CommonModule
  ],
  declarations: [
    ComponentHostDirective
  ],
  exports: [
    CommonModule,
    ComponentHostDirective
  ]
})
export class SharedModule {}

应用模块.ts
@NgModule({
  declarations: [
    ComponentHostDirective <== remove it
  ],
  imports: [
    ...
    SharedModule, // add this
    ...
  ]
})
export class AppModule { }

主页.module.ts
@NgModule({
  imports: [
    ...
    SharedModule, // add this
    ...
  ]
})
export class HomeModule { }

之后,您的appComponentHost属性将引用ComponentHostDirective实例。
另外,您将得到错误
expressionchangedafterithasbeencheckederror:表达式已更改
检查之后。上一个值:“未定义”。当前值:
“顾客”。
组件创建后。
不要在ngAfterViewInit钩子中更改绑定。改为使用ngOnInit
export class StatsComponent implements OnInit, OnDestroy {
  ...
  ngOnInit() {
    this.loadComponent();
  }

这篇文章非常详细地解释了这种行为(谢谢@maximus)。
最后你会看到结果:
Everything you need to know about the ExpressionChangedAfterItHasBeenCheckedError error

09-17 01:42