【问题标题】:How to add items to NgModule entryComponents runtime?如何向 NgModule entryComponents 运行时添加项目?
【发布时间】:2017-11-17 15:10:34
【问题描述】:

我有以下 Angular 代码:

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);
    }
}

还有contract-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;
}

还有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 数组中,因为我的应用不知道我将拥有哪些类型的小部件(将来)。

有什么方法可以在 runtime 上以编程方式将 ContractWidgetComponent 添加到我的 entryComponent,以便我可以在仪表板上动态加载我的小部件?

任何帮助将不胜感激。

【问题讨论】:

标签: angular angular-services


【解决方案1】:

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

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

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

【讨论】:

  • 不错!我忘记了动态编译部分(尽管我几天前读过你的文章)。我将删除我的答案以避免任何混淆:)
  • @GeorgeK,是的,你觉得这篇文章怎么样? :)
  • 我真的很喜欢整个系列,说实话:)。对 Angular 中一些关键概念的详细解释。谢谢你的好文章:)
  • 感谢您的客气话,这需要很多时间,但我很高兴社区受益。我现在正在写Zones in depth,所以请跟进以在完成时收到通知:)
  • 感谢您的帮助。它把我推向了正确的方向!
猜你喜欢
  • 1970-01-01
  • 2017-05-03
  • 2017-05-20
  • 2017-02-06
  • 2015-08-15
  • 1970-01-01
  • 2017-08-16
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多