Angular2 - 从模块动态加载组件 [英] Angular2 - Dynamically load component from module

查看:149
本文介绍了Angular2 - 从模块动态加载组件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

  export class MyComponent {
subcompPath =path-to -subcomp#SubcompClassName;
@ViewChild(placeholder,{read:ViewComponentRef})placeholderRef:ViewComponentRef;

/ *编译器,ComponentFactoryResolver注入的构造函数* /

loadSubcomponent(){
let [path,componentName] = this.subcompPath.split(# );
(< any> window).System.import(path)
.then((module:any)=> module [componentName])
.then((type:any) => {
return this._compiler.compileComponentAsync(type)
})
.then((factory:any)=> {
let componentRef = this.placeholderRef。 createComponent(factory,0);
});
}
}

我的子组件声明提供程序和内容,指令和管道。



现在RC6再次打破一切。组件无法声明指令和管道,但它们必须位于声明组件的模块中。
所以我必须加载SystemJS不是组件本身,而是模块。
好​​的,然后我应该使用

  return this._compiler.compileModuleAndAllComponentsAsync(type)

很好,但是如何获得这个特定组件的工厂的引用?这个工厂是我需要的,placeholderRef想要它的createComponent方法,对吧?



我试图从github挖掘出角度2的源代码,但它相当广泛,我应该尝试VS代码或某些东西,使用智能感知,但我很懒惰...我应该从文档中读取这些东西,这对于这个特定的参数来说是非常不成熟的,这是非常愚蠢的加载组件和模块WITHOUT路由器。



任何帮助不胜感激,我认为该解决方案很容易应用,但很难找到没有官方文档。

解决方案

根据yurzui的答案我来了以下代码:

  export class MyComponent {
subcompPath =path-to-subcompMODULE#SubcompClassName;
@ViewChild(placeholder,{read:ViewComponentRef})placeholderRef:ViewComponentRef;

/ *编译器,ComponentFactoryResolver注入的构造函数* /

loadSubcomponent(){
let [modulePath,componentName] = this.subcompPath.split(# );
(< any> window).System.import(modulePath)
.then((module:any)=> module [default])//或传递模块类名称
.then((type:any)=> {
return this._compiler.compileModuleAndAllComponentsAsync(type)
})
.then((moduleWithFactories:ModuleWithComponentFactories< any>)= > {
const factory = moduleWithFactories.componentFactories.find(x => x.componentType.name === componentName); // Crucial:componentType.name,而不是componentType !!
let componentRef = this.placeholderRef.createComponent(factory,0);
});
}
}


in my angular app I have the following:

export class MyComponent {
    subcompPath = "path-to-subcomp#SubcompClassName";
    @ViewChild("placeholder", { read: ViewComponentRef }) placeholderRef: ViewComponentRef;

/* Constructor where Compiler, ComponentFactoryResolver are injected */

    loadSubcomponent() {
        let [path, componentName] = this.subcompPath.split("#");
        (<any>window).System.import(path)
            .then((module: any) => module[componentName])
            .then((type: any) => {
                return this._compiler.compileComponentAsync(type)
            })
            .then((factory: any) => {
                let componentRef = this.placeholderRef.createComponent(factory, 0);
            });
    }
}

My sub-component declares providers and stuff, directives and pipes.

And now RC6 is out to break everything yet again. Components can't declare directives and pipes, but they must be in the module where the component is declared. So I have to load with SystemJS not the component itself but the module. Ok, and then I should use

return this._compiler.compileModuleAndAllComponentsAsync(type)

Fine, but how do I get a reference to the factory of this specific component? That factory is all I need, the placeholderRef wants it in its createComponent method, right?

I tried to dig into the angular2 source code from github but it's quite vast, I should try from VS Code or something, with intellisense, but I'm lazy...and I should read this stuff from documentation, which is quite lackluster in angular.io for this particular argument, which is lazy loading of components and modules WITHOUT the router.

Any help is appreciated, I think the solution is simple to apply but hard to find without official documentation.

解决方案

Based on yurzui's answer I've come to the following code:

export class MyComponent {
    subcompPath = "path-to-subcompMODULE#SubcompClassName";
    @ViewChild("placeholder", { read: ViewComponentRef }) placeholderRef: ViewComponentRef;

    /* Constructor where Compiler, ComponentFactoryResolver are injected */

    loadSubcomponent() {
        let [modulePath, componentName] = this.subcompPath.split("#");
        (<any>window).System.import(modulePath)
            .then((module: any) => module["default"])  // Or pass the module class name too
            .then((type: any) => {
                return this._compiler.compileModuleAndAllComponentsAsync(type)
            })
            .then((moduleWithFactories: ModuleWithComponentFactories<any>) => {
                const factory = moduleWithFactories.componentFactories.find(x => x.componentType.name === componentName); // Crucial: componentType.name, not componentType!!
                let componentRef = this.placeholderRef.createComponent(factory, 0);
            });
    }
}

这篇关于Angular2 - 从模块动态加载组件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆