Angular 5 - 动态组件模板加载

Posted

技术标签:

【中文标题】Angular 5 - 动态组件模板加载【英文标题】:Angular 5 - Dynamic component template loading 【发布时间】:2018-07-25 03:58:38 【问题描述】:

在我的 Angular 5 项目中,我需要在下载 API 数据后动态创建一个组件(我在里面有带有 Angular 标记的 html 代码 - 我需要在请求完成后编译它们),但我发现 AOT 存在问题.

我尝试使用来自该主题 Angular 4 | Template bind through innerHTML, component variables are not accessible (damContentRoot is this case)(以及来自该主题 How can I use/create dynamic template to compile dynamic Component with Angular 2.0?)的解决方案

这是我当前的代码:

import 
    Directive,
    OnChanges,
    Input,
    ComponentRef,
    ViewContainerRef,
    Compiler,
    ModuleWithComponentFactories,
    Component,
    NgModule,
    Type
 from '@angular/core';

import CommonModule from '@angular/common';
import  FormsModule, ReactiveFormsModule, NgForm    from '@angular/forms';
import JitCompilerFactory from '@angular/platform-browser-dynamic';





@Directive(selector: '[compile]')
export class CompileDirective implements OnChanges 
    @Input()compile : string;
    @Input()compileContext : any;

    compRef : ComponentRef < any >;

    constructor(private vcRef : ViewContainerRef, private compiler : Compiler) 

    ngOnChanges() 
        if (!this.compile) 
            if (this.compRef) 
                this.updateProperties();
                return;
            
            throw Error('You forgot to provide template');
        

        this
            .vcRef
            .clear();
        this.compRef = null;

        const component = this.createDynamicComponent(this.compile);
        const module = this.createDynamicModule(component);
        this
            .compiler
            .compileModuleAndAllComponentsAsync(module)
            .then((moduleWithFactories : ModuleWithComponentFactories < any >) => 
                let compFactory = moduleWithFactories
                    .componentFactories
                    .find(x => x.componentType === component);

                this.compRef = this
                    .vcRef
                    .createComponent(compFactory);
                this.updateProperties();
            )
            .catch(error => 
                console.log(error);
            );
    

    updateProperties() 
        for (var prop in this.compileContext) 
            this.compRef.instance[prop] = this.compileContext[prop];
        
    

    private createDynamicComponent(template : string) 
        @Component(selector: 'custom-dynamic-component', template: template)
        class CustomDynamicComponent 
        return CustomDynamicComponent;
    

    private createDynamicModule(component : Type < any >) 
        @NgModule(
            // You might need other modules, providers, etc... Note that whatever components
            // you want to be able to render dynamically must be known to this module
            imports: [CommonModule, FormsModule, ReactiveFormsModule],
            declarations: [component],
        )
        class DynamicModule 
        return DynamicModule;
    

&lt;ng-container *compile="this.pageData.html; context: this"&gt;&lt;/ng-container&gt;

但我遇到了错误: ERROR Error: Runtime compiler is not loaded

我也尝试过使用 JitCompilterFactory,但出现了类似的错误:https://github.com/angular/angular/issues/20639。

有什么方法可以在运行时使用 aot 编译添加组件?或者将它与 JIT 结合起来没有任何意义?

我已经阅读了有关动态组件加载 (https://blog.angularindepth.com/here-is-what-you-need-to-know-about-dynamic-components-in-angular-ac1e96167f9e) 的整个主题,但我仍然找不到解决方案,总是出现 JitCompilerFactory 错误。

【问题讨论】:

通过 hack 可能可以做到这一点,但我不知道 hack 是什么。我会说,如果你有很多这样的场景,他会一直与框架发生冲突,因为它不希望任何东西都是动态的 ***.com/a/45506470/7945055 也许 SystemJS 会解决这个问题? 嗨@PatrykPanek,查看我关于动态组件和响应式表单的帖子。在我的回答中,有一个 stackblitz 示例可以帮助您解决问题。 ***.com/questions/48753464/… @Narm 感谢您的回答,但在您的解决方案中,您使用的是 Compiler 库。我认为它不适用于 Angular 5 中的 AOT 运行时。 【参考方案1】:

我有带有 Angular 标记的 HTML 代码 - 我需要在请求完成后编译它们

我所需要的只是一种基于组件选择器将组件加载到动态字符串中的方法,我编写的 ngx-dynamic-hooks-library 可能会有所帮助。因为我也没有找到任何其他好的解决方案,所以我已经为这个确切的目的创建了它。

它适用于 JiT 和 Aot 模式,因为它根本不依赖运行时编译器,因此您不必担心这一点。看到它工作here。

【讨论】:

以上是关于Angular 5 - 动态组件模板加载的主要内容,如果未能解决你的问题,请参考以下文章

是否可以将服务注入 Angular 1.5 组件的 templateUrl 属性?

2020 -02- 07组件与模板

如何将动态模板加载到角度组件中

Angular 5:从组件访问元素内部 html 以获取动态生成的元素

角度 5 延迟加载与动态加载

Angular 2 - 使用 ComponentResolver 加载在运行时下载的组件