app
|-plugins
|-plugin1
|-config.json
|-plugin1.module.ts
|-plugin1.component.ts
|-plugin2
|-config.json
|-plugin2.module.ts
|-plugin2.component.ts
如上所示,我有 “app / plugins” 文件夹,其中包含插件。每个插件将包含一个“config.json”文件,该文件将告诉一些配置,包括 -
{
path: "feature1",
moduleFile: "feature1.module",
moduleClassName: "Feature1Module"
}
所以我想要的是,在应用程序引导之前,它将扫描 “app / plugins” 文件夹并加载所有插件配置,并懒惰地注册所有模块路由。对于上面的例子,路线将是
{
path: "feature1",
loadChildren: "app/plugins/plugin1/plugin1.module#Plugin1Module"
}
这样,我们可以将新插件放入插件文件夹并刷新应用程序,我们新删除的插件已启动并运行。
任何人都知道如何实现这一目标?
注意:我在angular2 latest(2.1.0)
答案 0 :(得分:14)
I'm looking for the same behavior than the one you're describing and I think I've found how to do it, thanks to this github issue : Lazy loading components without Route
Here is the code I've written to do it : plunker here
First : dynamic.module.ts, the dynamically loaded module and its component
import { Component, NgModule } from '@angular/core'
@Component({
selector: 'my-test',
template: `<h1>html template of TestComponent from DynamicModule</h1>`
})
export class TestComponent { }
@NgModule({
declarations: [TestComponent],
exports: [TestComponent]
})
export class DynamicModule { }
Second : here is the component which dynamically loads module when you give it the module path.
import {
Component,
ViewContainerRef,
Compiler,
ComponentFactory,
ComponentFactoryResolver,
ModuleWithComponentFactories,
ComponentRef,
ReflectiveInjector,
SystemJsNgModuleLoader } from '@angular/core';
class ModuleNode {
modulePath: string;
componentName: string;
}
@Component({
moduleId: module.id,
selector: 'widgetContainer',
templateUrl: './widgetContainer.component.html'
})
export class WidgetContainerComponent {
widgetConfig: string;
module: ModuleNode;
cmpRef: ComponentRef<any>;
constructor(private widgetService: WidgetLoader,
private viewref: ViewContainerRef,
private resolver: ComponentFactoryResolver,
private loader: SystemJsNgModuleLoader,
private compiler: Compiler){}
openWebApp(menu:any) {
this.loader.load(menu.modulePath) // load the module and its components
.then((modFac) => {
// the missing step, need to use Compiler to resolve the module's embedded components
this.compiler.compileModuleAndAllComponentsAsync<any>(modFac.moduleType)
.then((factory: ModuleWithComponentFactories<any>) => {
return factory.componentFactories.find(x => x.componentType.name === menu.componentName);
})
.then(cmpFactory => {
// need to instantiate the Module so we can use it as the provider for the new component
let modRef = modFac.create(this.viewref.parentInjector);
this.cmpRef = this.viewref.createComponent(cmpFactory, 0, modRef.injector);
// done, now Module and main Component are known to NG2
});
});
}
ngOnDestroy() {
if (this.cmpRef) {
this.cmpRef.destroy();
}
}
}
What do you think about that? Does it help? Thanks a lot for your feedback.