Angular 5 - 动态组件模板加载

时间:2018-02-14 14:27:19

标签: angular typescript templates compilation runtime

在我的Angular 5项目中,我需要在下载API数据后动态创建一个组件(我的HTML代码里面有Angular标记 - 我需要在请求完成后编译它们),但我看到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;
    }
}

<ng-container *compile="this.pageData.html; context: this"></ng-container>

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

我也试过使用JitCompilterFactory,但我收到错误:https://github.com/angular/angular/issues/20639

有没有办法在运行时通过编译添加组件?或者将它与JIT结合在一起并没有任何意义?

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

1 个答案:

答案 0 :(得分:0)

我的Angular标记中包含HTML代码-请求完成后,我需要对其进行编译

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

它完全不依赖于运行时编译器,因此可与JiT和Aot模式一起使用,因此您不必为此担心。看到它运作here