'Angular, compile and create components at runtime
I'm trying to make a document generation tool in angular and I'm hitting a challenge with how I would allow a user to dynamically create content.
My components I want to create could have arbitrary models and behavior so I don't think I could use a shared component.
The components I'm describing would not exist at compile time.
I see some documentation for rendering dynamic components. However it mentions that you must list the "dynamic" component in entryComponents
in the ngModule
. which will not work for my scenario.
Is there another mechanism to get this effect?
Solution 1:[1]
You can create a module and a component on-the-fly, apply decorators to it and then compile it all. Then you will be able to access the compiled components:
@ViewChild('vc', {read: ViewContainerRef}) vc: ViewContainerRef;
constructor(private _compiler: Compiler,
private _injector: Injector,
private _m: NgModuleRef<any>) {
}
ngAfterViewInit() {
const template = '<span>generated on the fly: {{name}}</span>';
const tmpCmp = Component({template: template})(class {
});
const tmpModule = NgModule({declarations: [tmpCmp]})(class {
});
this._compiler.compileModuleAndAllComponentsAsync(tmpModule)
.then((factories) => {
const f = factories.componentFactories[0];
const cmpRef = f.create(this._injector, [], null, this._m);
cmpRef.instance.name = 'dynamic';
this.vc.insert(cmpRef.hostView);
})
}
For this approach to work you need to bring compiler to the runtime. For more details on dynamic components read the article:
Solution 2:[2]
I find out solution that works with Angular 13, and want to share with you.
const importedFile = await import('pathToModule');
const module: NgModuleRef<E> = createNgModuleRef<E>(importedFile[moduleClassName], this._injector);
this.containerRef.createComponent(importedFile[componentClassName], { ngModuleRef: module });
In Angular 13 the Compiler
is depracated. The entire compilation process is done under the hood, even if we dynamically import some module/component.
My solution require add an export with component we want to create in the imported module file.
export * from './containers/container.component';
**Instead of importing file you can create component and modules on the fly (like example above) but instead of compiler use just createNgModuleRef
and createComponent
functions **
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Max Koretskyi |
Solution 2 | Piotr B. |