入口组件的角度注册表

时间:2018-09-19 13:07:18

标签: angular dynamic plugins widget dashboard

我需要安装一个组件,该组件显示可配置的小部件仪表板。 主应用程序应提供一个仪表板组件,该组件基于配置在网格中显示小部件。 对于每个窗口小部件,将实例化窗口小部件容器组件,该组件将调用返回组件类型(即装饰类)的服务。该类型用于解析其组件工厂,后者用于在小部件容器内的ViewComponentRef内创建组件。

widget-container.html:

<div class="placeholder" #target></div>
<div class="loader">
    <mat-spinner [diameter]="50"></mat-spinner>
</div>

widget-container.ts:

constructor(
    private readonly _el: ElementRef,
    private readonly _renderer: Renderer2,
    private _componentFactoryResolver: ComponentFactoryResolver,
    private readonly _widgetService: WidgetService
) {}

ngOnInit(): void {
    const componentClass = this._widgetService.getWidget(this.widgetDefinition.componentName);
    const factory = this._componentFactoryResolver.resolveComponentFactory(componentClass);
    this._componentRef = this._viewContainer.createComponent(factory);
    const newItem: WidgetBase = this._componentRef.instance;
}

现在,该应用程序需要使用可插入其他功能的模块进行扩展。假设这些模块已作为npm插件包导入到应用中:

main-app.module.ts:

import { Plugin1Module } from "@mycompany/plugin1";

[...]

@NgModule({
    imports: [..., Plugin1Module], [...]
})
export class MainAppModule {}

因此,由于Plugin1Module是由谁开发的AOT编译的,所以我的窗口小部件服务无法再返回给定字符串的Component Type,因此现在需要返回的是ComponentFactory。因此,它成为一项服务,必须能够检索到该点加载的所有组件工厂的列表,即使是从其他位置导入的模块中,也可以找到给定某种标识符的特定工厂。 我该如何实现?我试图了解要在此服务中注入什么:哪个角度服务提供了所有现有组件工厂的列表?

1 个答案:

答案 0 :(得分:0)

摆弄代码,我在小部件解析器服务中找到了这个骇人听闻的解决方案:

getWidgetComponentFactory(componentName: string): ComponentFactory<WidgetBase> {
    let ret: ComponentFactory<WidgetBase> = null;
    let found = false;
    (this._resolver as any)._factories.forEach((f: ComponentFactory<any>) => {
        if (found) {
            return;
        }

        if (f.componentType.name === `${componentName}Component`) {
            ret = f;
            found = true;
        }
    });
    return ret;
}

我知道ComponentFactoryResolver服务上有_factories,只是没有公开。唯一的公共函数将Type <{}>作为参数,但是我没有实际的Component类,我只拥有类的名称,因此我需要从所有已知工厂的列表中手动找到工厂倾斜。

有更清洁的解决方案吗?