入口组件的 Angular 注册表

Posted

技术标签:

【中文标题】入口组件的 Angular 注册表【英文标题】:Angular registry for entry components 【发布时间】:2019-02-23 16:08:39 【问题描述】:

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

widget-container.html:

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

小部件容器.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。因此,它成为一项服务,必须能够检索在该点加载的所有组件工厂的列表,即使是从其他地方导入的模块,并找到给定某种标识符的特定工厂。 我怎样才能做到这一点?我试图了解在此服务中注入了什么:哪个 Angular 服务提供了所有现有组件工厂的列表?

【问题讨论】:

【参考方案1】:

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

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 === `$componentNameComponent`) 
            ret = f;
            found = true;
        
    );
    return ret;

我知道 _factories 存在于 ComponentFactoryResolver 服务中,它只是没有暴露。唯一的公共函数将 Type 作为参数,但我没有实际的 Component 类,我只有类的名称,所以我需要从所有已知工厂列表中手动查找工厂到角度。

有更清洁的解决方案吗?

【讨论】:

澄清一下,自 Angular 9 以来,此解决方案不再有效。据我所知,在不手动维护字符串的情况下,仍然没有简单的方法可以从字符串动态创建组件->类型映射.有关此主题的讨论,请参阅 github.com/angular/angular/issues/24360。

以上是关于入口组件的 Angular 注册表的主要内容,如果未能解决你的问题,请参考以下文章

Angular动态注册组件(controller,service...)

angular 6 ionic 4 默认组件未注册

Angular & ag-grid:无法使用 frameworkComponents 注册框架组件

利用angular4和nodejs-express构建一个简单的网站—用户注册之ReactiveForm

Angular 10 在另一个内部使用一个组件(错误:不是已知元素)

Vue注册组件的几种方式,你都知道吗?