Angular 7从选择器解析组件工厂

时间:2019-03-26 02:20:10

标签: angular

我正在开发一个Angular 7库,它具有先前声明的组件(在相同或更高模块中)的知识。我现在只有组件选择器,希望在容器视图中创建该组件。

可以做到吗?我可以在不维护自己的注册表的情况下从编译器内部获取工厂信息吗?

谢谢

1 个答案:

答案 0 :(得分:0)

如果您可以获得声明组件的模块以及组件的选择器,则下面的方法将起作用。

首先,创建一个辅助方法以获取装饰器注释的类型(我认为这不适用于IE或aot编译):

/**
 * gets a decorator of the requested type off of the given decorated type
 * @param decoratedType to get decorator annotations off of
 * @param decoratorType to search for out of all the decorators on decoratedType
 * @returns decorator from the decoratedType of the decoratorType
 */
export function decoratorOfType<T>(decoratedType: Type<any>, decoratorType: Type<T>): T {
    // get all decorators off of the provided type
    return Reflect.getOwnPropertyDescriptor(decoratedType, '__annotations__').value.find((annotation: any) =>
        // get the decorator that matches the requested type
        annotation instanceof decoratorType
    );
}

此函数将使获取组件所声明的模块的@NgModule装饰器(在我的示例中为AppModule)变得容易:

const ngModuleDecorator = decoratorOfType(AppModule, NgModule);

使用模块装饰器,您可以遍历其声明,并使用@Component装饰器和设置为您要查找的选择器(在我的示例中为app-counter)进行查找。

const componentType = ngModuleDecorator.declarations.find((declaration: Type<any>) => {
    // get the @Component decorator
    const declarationDecorator = decoratorOfType(declaration, Component);

    // find a declaration with the @Component decorator (not a @Directive) with the requested selector
    return declarationDecorator != null && declarationDecorator.selector === 'app-counter';
});

获得组件的类型后,可以使用ViewContainerRef和ComponentFactoryResolver创建组件,就像other tutorials向您展示如何动态创建组件:

// get the component factory using the component type
const componentFactory = this._componentFactoryResolver.resolveComponentFactory(componentType as Type<any>);

// fill the content using the component factory
this.dynamicContentDiv.clear();
this.dynamicContentDiv.createComponent(componentFactory);

我创建了一个working example on StackBlitz,它会根据所选选择器的内容在两个组件之间切换: