简体   繁体   English

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

[英]Angular: How to pass data in ngComponentOutlet through Injector

I'm trying to dynamically create and show component and i need to pass some data into it, so that it knows what to show.我正在尝试动态创建和显示组件,我需要将一些数据传递给它,以便它知道要显示什么。

Here is my code:这是我的代码:

html part: 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>

Components:组件:

export class ProjectsComponent implements OnInit {

  details: Component;
  private showWp: boolean;

  constructor() {
  }


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

and the component i want dynamically create and show:以及我想要动态创建和显示的组件:

export class ProjectComponent implements OnInit {

  project: Project;

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

NgModule: Ng 模块:

@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]
})

The error message:错误信息:

ProjectsComponent.html:15 ERROR Error: No component factory found for [object Object]. ProjectsComponent.html:15 ERROR 错误:找不到 [object Object] 的组件工厂。

How can i do the task?我怎样才能完成任务? Thanks.谢谢。

If you open the code of NgComponentOutlet directive:如果打开NgComponentOutlet指令的代码:

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

you can notice that it takes ngComponentOutlet input that should have type Type<any> but you're passing object to it.您可以注意到它需要ngComponentOutlet输入,该输入应该具有Type<any>但是您将对象传递给它。

Also we can see that this directive can take Injector as @Input .我们也可以看到这个指令可以将Injector作为@Input So lets leverage this knowledge to do your task.因此,让我们利用这些知识来完成您的任务。

For example we wrote template like:例如,我们编写的模板如下:

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

Now lets declare component and injector properties in component class:现在让我们在组件类中声明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);
  }
}

and your ProjectComponent now uses angular DI mechanism to get data we passed to injector:并且您的ProjectComponent现在使用 angular DI 机制来获取我们传递给注入器的数据:

export class ProjectComponent {
  name: string;

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

Stackblitz Example Stackblitz 示例

Thanks to yuzui's comment I managed to get something working感谢 yuzui 的评论,我设法得到了一些工作

The full runnable code can be found on Stackblitz完整的可运行代码可以在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; } }

Hey there change widgets to widgets = [], otherwise angular will keep calling the method in the ngFor loop.嘿,将小部件更改为小部件 = [],否则 angular 将继续在 ngFor 循环中调用该方法。 If you console log in the constructor for the component you find this is happening.如果您控制台登录组件的构造函数,您会发现这种情况正在发生。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM