2017-06-15 43 views
1

我有下面这段代码角:如何添加项目到NgModule entryComponents运行时?

dashboard.component.ts

import {Component, AfterViewInit, ComponentFactoryResolver, ViewContainerRef, OnInit, Input} from "@angular/core"; 
import {WidgetItem} from "../modules/widget-item"; 
import {WidgetComponent} from "../modules/widget.component"; 
import {DashboardService} from "./dashboard.service"; 

@Component({ 
    selector: 'dashboard', 
    templateUrl: './dashboard.component.html', 
    styleUrls: ['./dashboard.component.css'] 
}) 

export class DashboardComponent implements OnInit, AfterViewInit { 
    @Input() widgets: WidgetItem[]; 

    constructor(
     private dashboardService: DashboardService, 
     private componentFactoryResolver: ComponentFactoryResolver, 
     private viewContainerRef: ViewContainerRef 
    ) {} 

    ngOnInit(): void { 
     this.widgets = this.dashboardService.getWidgets(); 
    } 

    ngAfterViewInit(): void { 
     this.loadDashboard(); 
    } 

    private loadDashboard(): void { 
     this.viewContainerRef.clear(); 
     if(this.widgets) { 
      for (let widget of this.widgets) { 
       let componentFactory = this.componentFactoryResolver.resolveComponentFactory(widget.component); 
       let componentRef = this.viewContainerRef.createComponent(componentFactory); 
       (<WidgetComponent>componentRef.instance).data = widget.data; 
      } 
     } 
    } 

} 

而且dashboard.service.ts

import {Injectable}   from '@angular/core'; 
import {WidgetItem} from "../modules/widget-item"; 

@Injectable() 
export class DashboardService { 
    private dashboardWidgets: WidgetItem[]; 
    constructor() { 
     this.dashboardWidgets = []; 
    } 

    getWidgets() { 
     console.log('get widgets'); 
     return this.dashboardWidgets; 
    } 

    addWidget(widget: WidgetItem): void { 
     console.log('add widget', widget); 
     this.dashboardWidgets.push(widget); 
    } 
} 

而且合同widget.component.ts

import {Component} from "@angular/core"; 
import {WidgetComponent} from "./widget.component"; 

@Component({ 
    selector: 'contract-widget', 
    templateUrl: './contract-widget.component.html' 
}) 

export class ContractWidgetComponent implements WidgetComponent { 
    data: any; 
} 

and widget.component.ts

export interface WidgetComponent { 
    data: any; 
} 

和widget-item.ts

import {Type} from "@angular/core"; 
export class WidgetItem { 
    constructor(public component: Type<any>, public data:any) {} 
} 

我尝试做使用componentfactoryresolver被动态地加载在我的仪表盘上的小部件。当我手动添加ContractWidgetComponent到我的app.component的entryComponents时,这是完美的。但是,我想要完成的是,我可以在不知道它们存在于我的应用程序中的情况下将小部件加载到我的仪表板中。我已经分居的代码,所以我的文件夹结构是这样的:

/app -- contains app.module.ts, app-routing.module.ts and app.component.ts 
/app/parts -- contains dahsboard.component.ts and dahsboard.service.ts 
/app/modules -- contains contract-widget.component.ts widget.component.ts and widget-item.ts 

在我的小工具我还设置一个组成部分,所以我可以使用该组件作为loadChildren动态加载的组件。 (在我的应用程序/模块中,我确实有更多的代码与其他组件和服务的特定功能,这不需要在这里解释我的问题)。

我想要做的是能够在我的/ app/modules中开发另一个模块,并在那里添加所需的文件,并让我的仪表板能够在我的模块中显示任何新的小部件,而无需更改我的代码/ app或/ app/parts目录。

主要部件都正常工作,但是当我尝试加载在我的仪表板与loadDashboard()我得到以下错误的部件:

ERROR Error: Uncaught (in promise): Error: No component factory found for ContractWidgetComponent. Did you add it to @NgModule.entryComponents? 
Error: No component factory found for ContractWidgetComponent. Did you add it to @NgModule.entryComponents? 

这是有道理的,因为我不希望添加ContractWidgetComponent给我的/app/app.module.ts entryComponents数组,因为我的应用程序不知道我将有什么类型的小部件(将来)。

有什么办法以编程方式将ContractWidgetComponent添加到我的entryComponent上运行时所以我可以在我的仪表板上动态加载我的小部件?

任何帮助将不胜感激。

+0

请考虑接受[我的回答(https://stackoverflow.com/a/44562681/2545680) –

回答

1

What I want to do is to be able to develop another module inside my /app/modules and just add the needed files there and have my dashboard be able to just display any new widget in my modules without changing code in my /app or /app/parts directory.

是的,你可以这样做。只需定义一个模块声明中指定的contract-widget.component.ts模块,动态加载该模块并使用compileModuleAndAllComponentsAsync编译器API生成模块的所有工厂。然后您可以访问这些工厂并动态地实例化组件。

欲了解更多详情,请阅读Here is what you need to know about dynamic components in Angular

+1

尼斯!我忘记了动态编译部分(尽管我几天前读过你的文章)。我会删除我的答案,以避免任何混淆:) –

+0

@乔治克,是的,你是如何看待这篇文章的? :) –

+1

我真的很喜欢整个系列,说实话:)。 Angular中的一些关键概念的一个很好的,详细的解释。感谢您的好写作:) –