Reputation: 1962
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);
}
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.
Upvotes: 1
Views: 1677
Reputation: 5036
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
Upvotes: 0
Reputation: 214295
I would solve your problem by using compiler.clearCacheFor
method:
compiler.clearCacheFor(decoratedCmp);
See also
Upvotes: 1