如何注入动态创建的组件的服务

use*_*875 5 angular

export interface InfoPanelComponent {
    data: any;
}

export class ComplaintsComponent implements OnInit, InfoPanelComponent {
   data: any;             
   constructor(private navigationService: NavigationService, private activatedRoute: ActivatedRoute) {
   }

  onCancelClicked() {
      console.log(this.navigationService);
      this.navigationService.hidePanel(this.data.key, this.activatedRoute);
  }
}
Run Code Online (Sandbox Code Playgroud)

问题是,这this.navigationService是未定义的。服务本身在 中提供,app.modules.ts并且可以成功注入到其他组件中。

我想它不起作用的原因是上面的组件(以及将来的更多组件)是动态创建的:

private addPanel(item: InfoPanelItem, itemKey: string): void {
      const componentFactory = this.componentFactoryResolver.resolveComponentFactory(item.component);
      const viewContainerRef = this.infopanelHost.viewContainerRef;

      // create new component
      const componentRef = viewContainerRef.createComponent(componentFactory);

      (<InfoPanelComponent>componentRef.instance).data = item.data;   
  }
Run Code Online (Sandbox Code Playgroud)

我想因此没有注入服务。有没有办法一般地注入组件所需的所有依赖项?请注意,这ComplaintsComponent只是一个示例,还有更多示例可能需要不同的服务。

Nar*_*arm 7

您可以通过这两种方式为动态组件提供服务。在我的示例中,我将演示在容器组件DynamicContainerComponent.

首先在容器组件中导入您需要的所有服务。在我的例子AExampleServiceBExampleService.

动态容器组件

import {
  Component, ViewChild, AfterContentInit, ComponentFactoryResolver, Compiler, ViewContainerRef, NgModule, NgModuleRef,
} from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AExampleService } from './services/AExampleService';
import { BExampleService } from './services/BExampleService';


@Component({
  selector: 'dynamic-container',
  template: `<ng-container #vc></ng-container>`,
  styleUrls: ['./dynamic-container.component.css']
})
export class DynamicContainerComponent implements AfterContentInit{
  @ViewChild('vc', { read: ViewContainerRef }) _container: ViewContainerRef;

  constructor(private aExampleService: AExampleService) { }

  ngAfterContentInit(){
    this.addDynamicComponent();
  }

  private addDynamicComponent(): void{...}
}
Run Code Online (Sandbox Code Playgroud)

现在您可以通过在动态组件中使用依赖注入来使用AExampleService和。这个例子展示了两种方法:BExampleService

  • 服务的直接 DIBExampleService到动态组件中
  • 注射父组件DynamicContainerComponent动态组件,将暴露AExampleService

看看里面的代码 private addDynamicComponent(): void{...}

添加动态组件()

private addDynamicComponent(): void{

  @Component({
    template: `<h2>This is a dynamic component</h2>`,
    styleUrls: ['./dynamic.component.css']
  })
  class DynamicComponent {
    constructor(
      public _parent: DynamicContainerComponent,
      private bExampleService: BExampleService) { }

    private someFunctionA(): void {
      this._parent.aExampleService.doSomthingA();
    }

    private someFunctionB(): void {
      this.bExampleService.doSomthingB();
    }
  }
  @NgModule({
    imports: [
      BrowserModule
    ],
    declarations: [DynamicComponent],
  }) class DynamicModule { }

  const mod = this.compiler.compileModuleAndAllComponentsSync(DynamicModule);
  const factory = mod.componentFactories.find((comp) =>
    comp.componentType === DynamicComponent
  );

  this.cmpRef = this._container.createComponent(factory);
}
Run Code Online (Sandbox Code Playgroud)

既不通知AExampleService或者BExampleService被宣布为提供商活力的组成部分,而是它们被声明为提供商模块包含DynamicContainerComponent