Angular:如何通过Injector在ngComponentOutlet中传递数据

时间:2018-01-10 13:04:15

标签: angular

我正在尝试动态创建和显示组件,我需要将一些数据传递给它,以便它知道要显示的内容。

这是我的代码:

html部分:

<div class="basicContainer">
  <div class="projectsTreeContainer">


    <input type="text" id="searchWord" placeholder="Search through projects"/>

    <button (click)="loadAddProject()">Add new Project</button>

    <app-projects-tree (onLoadProjectDetails)="loadProjectDetails($event)"
                       (onLoadWpDetails)="loadWpDetails($event)"
                       (onSelectAndLoadJobDetails)="loadJobDetails($event)"></app-projects-tree>
  </div>

  <div class="infoContainer">
    <ng-container *ngComponentOutlet="details"></ng-container>
  </div>

</div>

组件:

export class ProjectsComponent implements OnInit {

  details: Component;
  private showWp: boolean;

  constructor() {
  }


  loadProjectDetails(project: BasicProject): void {
     this.details = new ProjectComponent(project);
  }

我想要的组件动态创建并显示:

export class ProjectComponent implements OnInit {

  project: Project;

  constructor(basicProject: BasicProject) {
    this.project = new Project();
    this.project.name = basicProject.name ;
  }

NgModule:

@NgModule({
  declarations: [
    AppComponent,
    NavbarComponent,
    LoginComponent,
    ProjectsComponent,
    ProjectComponent,
    ProjectsTreeComponent,
    TreeProjectComponent,
    TreeWpComponent,
    WpComponent,
    JobComponent,
    AddProjectComponent
  ],
  imports: [
    BrowserModule,
    FormsModule,
    RouterModule.forRoot(
      AppRoutes.appRoutes,
      // {enableTracing: true} // <-- debugging purposes only
    ),
    HttpClientModule,
    HttpModule
  ],
  providers: [
    AuthenticationService,
    ProjectsService,
    CanActivateAuthGuard,
    {
      provide: HTTP_INTERCEPTORS,
      useClass: AuthInterceptor,
      multi: true
    }],
  bootstrap: [AppComponent],
  entryComponents: [ProjectComponent, WpComponent, JobComponent, AddProjectComponent]
})

错误消息:

  

ProjectsComponent.html:15错误错误:找不到组件工厂   [object Object]。

我该怎么办? 感谢。

3 个答案:

答案 0 :(得分:2)

如果您打开NgComponentOutlet指令的代码:

@Directive({selector: '[ngComponentOutlet]'})
export class NgComponentOutlet implements OnChanges, OnDestroy {
  @Input() ngComponentOutlet: Type<any>;
  @Input() ngComponentOutletInjector: Injector;

您可以注意到ngComponentOutlet输入需要输入类型Type<any>,但您要将对象传递给它。

此外,我们可以看到此指令可以Injector作为@Input。因此,让我们利用这些知识来完成您的任务。

例如,我们编写了如下模板:

<ng-container *ngComponentOutlet="component; injector: injector"></ng-container>

现在让我们在组件类中声明componentinjector属性:

@Component({...})
export class AppComponent  {

  component: Type<any>;
  injector: Injector;

  constructor(private inj: Injector) {}

  ngOnInit() {
    this.component = ProjectComponent; // note: we're passing type here
    this.injector = Injector.create([
      { provide: BasicProject, useValue: new Project('test name') }
    ], this.inj);
  }
}

并且您的ProjectComponent现在使用角度DI机制来获取我们传递给进样器的数据:

export class ProjectComponent {
  name: string;

  constructor(project: BasicProject) {
    this.name = project.name;
  }
}

<强> Stackblitz Example

答案 1 :(得分:0)

感谢yuzui的评论,我设法得到了一些工作

可以在Stackblitz

上找到完整的可运行代码

export class AppComponent  {
  name = 'Dynamic components in Angular 5';
  private injectors = {};

  constructor(private inj: Injector) {
  }

  get widgets() {
    return [
      {id: 1, widgetType:'child-component', settings: { showSecondLine: false} },
      {id: 2, widgetType:'child2-component', settings: { text: 'helloooooooooo'} },
      ];
  }
  
  getComponent(config: WidgetConfiguration) {
    switch (config.widgetType) {
      case 'child-component':
        return ChildComponent;
      case 'child2-component':
        return Child2Component;
    }
  }

   getInjector(config: WidgetConfiguration) {
    let inject = this.injectors[config.id];
    if (!inject) {
      inject = Injector.create([
        { provide: GeneralSettings, useValue: config.settings }
      ], this.inj);
      this.injectors[config.id] = inject;
    }

    return inject;
  }
}

答案 2 :(得分:0)

嘿,将小部件更改为小部件= [],否则angular将继续在ngFor循环中调用该方法。如果您通过控制台登录组件的构造函数,则会发现这种情况正在发生。