How can I use/create dynamic template to compile dynamic Component with Angular 2.0?

后端 未结 15 1908
忘掉有多难
忘掉有多难 2020-11-21 05:14

I want to dynamically create a template. This should be used to build a ComponentType at runtime and place (even replace) it somewhere inside of the ho

15条回答
  •  情话喂你
    2020-11-21 05:49

    I want to add a few details on top of this very excellent post by Radim.

    I took this solution and worked on it for a bit and quickly ran into some limitations. I'll just outline those and then give the solution to that as well.

    • First of all I was unable to render dynamic-detail inside a dynamic-detail (basically nest dynamic UIs inside each other).
    • The next issue was that I wanted to render a dynamic-detail inside one of the parts that was made available in the solution. That was not possible with the initial solution either.
    • Lastly it was not possible to use template URLs on the dynamic parts like string-editor.

    I made another question based on this post, on how to achieve these limitations, which can be found here:

    recursive dynamic template compilation in angular2

    I’ll just outline the answers to these limitations, should you run into the same issue as I, as that make the solution quite more flexible. It would be awesome to have the initial plunker updated with that as well.

    To enable nesting dynamic-detail inside each other, You'll need to add DynamicModule.forRoot() in the import statement in the type.builder.ts

    protected createComponentModule (componentType: any) {
        @NgModule({
        imports: [
            PartsModule, 
            DynamicModule.forRoot() //this line here
        ],
        declarations: [
            componentType
        ],
        })
        class RuntimeComponentModule
        {
        }
        // a module for just this Type
        return RuntimeComponentModule;
    }
    

    Besides that it was not possible to use inside one of the parts being string-editor or text-editor.

    To enable that you'll need to change parts.module.ts and dynamic.module.ts

    Inside parts.module.ts You'll need to add DynamicDetail in the DYNAMIC_DIRECTIVES

    export const DYNAMIC_DIRECTIVES = [
       forwardRef(() => StringEditor),
       forwardRef(() => TextEditor),
       DynamicDetail
    ];
    

    Also in the dynamic.module.ts you'd have to remove the dynamicDetail as they are now part of the parts

    @NgModule({
       imports:      [ PartsModule ],
       exports:      [ PartsModule],
    })
    

    A working modified plunker can be found here: http://plnkr.co/edit/UYnQHF?p=preview (I didn’t solve this issue, I’m just the messenger :-D)

    Finally it was not possible to use templateurls in the parts created on the dynamic components. A solution (or workaround. I’m not sure whether it’s an angular bug or wrong use of the framework) was to create a compiler in the constructor instead of injecting it.

        private _compiler;
    
        constructor(protected compiler: RuntimeCompiler) {
            const compilerFactory : CompilerFactory =
            platformBrowserDynamic().injector.get(CompilerFactory);
            this._compiler = compilerFactory.createCompiler([]);
        }
    

    Then use the _compiler to compile, then templateUrls are enabled as well.

    return new Promise((resolve) => {
            this._compiler
                .compileModuleAndAllComponentsAsync(module)
                .then((moduleWithFactories) =>
                {
                    let _ = window["_"];
                    factory = _.find(moduleWithFactories.componentFactories, { componentType: type });
    
                    this._cacheOfFactories[template] = factory;
    
                    resolve(factory);
                });
        });
    

    Hope this helps someone else!

    Best regards Morten

提交回复
热议问题