1

I have a dynamic component which receives its template in runtime and is compiled on the fly with the compileModuleAndAllComponentsSync method of Compiler from '@angular/core'.

Here is the code I use to get the componentFactory of the runtime component (please see the Plunker for complete code, all the interesting stuff is in runtime-content.component.ts)

private createComponentFactorySync(compiler: Compiler, metadata: Component): ComponentFactory<any> {
    let decoratedCmp = Component(metadata)(RuntimeComponent);

    @NgModule({ imports: [CommonModule], declarations: [decoratedCmp] })
    class RuntimeComponentModule { }

    let module: ModuleWithComponentFactories<any> = compiler.compileModuleAndAllComponentsSync(RuntimeComponentModule);

    return module.componentFactories.find(f => f.componentType === decoratedCmp);
}

enter image description here

It all works fine and the dynamic template is working fine the first time it is compiled. For my use case however I need to be able to change the template and recompile several times. But the second time I try to compile I get the error

"Type RuntimeComponent is part of the declarations of 2 modules: RuntimeComponentModule and RuntimeComponentModule!"

This of course makes sense since it does compile into another module of the same type. So my idea has been to try to unload the previously created module but cannot find any way to do that.

Anyone have an idea to acheive what I'm trying to do? Maybe by unloading the module or perhaps in another way. I have provided a working plunker to show the problem. Press the 'compile' button which will compile the dynamic template which will work fine (pressing the 'Inc' button increases the value). Pressing compile a second time will raise the error described above and the component stops working.

Plunker

2
  • Please clarify your specific problem or add additional details to highlight exactly what you need. As it's currently written, it’s hard to tell exactly what you're asking. See the How to Ask page for help clarifying this question. Commented Apr 2, 2017 at 19:46
  • the Plunker is not working.Please update it.I am searching for this kind of thing from last week.Your example is exactly what I need.Please update it.So I can test,I also want to compile javascript with template. @Richard Houltz Thanks IA Commented Sep 2, 2019 at 6:02

2 Answers 2

1

I would solve your problem by using compiler.clearCacheFor method:

compiler.clearCacheFor(decoratedCmp);

Plunker Example

See also

Sign up to request clarification or add additional context in comments.

1 Comment

Almost to easy ;) And it was sitting there in front of me the whole time. Nice!
0

Another solution would be to declare a new class for each new component and don't re-use the same RuntimeComponent each time.

protected createNewComponent(tmpl: string) {

    @Component({
        selector: `runtime-component-dynamic`,
        template: tmpl
    })
    class RuntimeComponent {
        name: string = 'Tim Jelly';
        value: number = 42;

        incValue() {
            this.value++;
        }
    }

    return RuntimeComponent;
}

See Plunker

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.