I've taken over an old Angular project at my work and I'm tasked with upgrading it from version 6 to 14. I've gone one version at a time as recommended by the Angular Update Guide. But now at version 13 I'm stuck at an issue with some dynamically created components.
Inside the dynamic component there are two functions: createNewComponent(template: string) and createComponentModule(componentType: any)
createNewComponent creates a component and accepts a string, which is the value passed to the function to be the dynamically created component's template.
createComponentModule created a ComponentModule and accepts a component, which is the new dynamically created component being passed to the function to be added to the newly created ComponentModules declarations and entryComponents.
The entire dynamic component looks like this:
import { Component, Input, NgModuleFactory, Compiler, SimpleChanges, NgModule } from "@angular/core";
import { SharedModule } from "../shared.module";
@Component({
selector: 'dynamic',
template: `<ng-container *ngComponentOutlet="dynamicComponent;
ngModuleFactory: dynamicModule;"></ng-container>`
})
export class DynamicComponent {
dynamicComponent: any;
dynamicModule: NgModuleFactory<any>;
@Input() html: string;
constructor(private compiler: Compiler) {
}
ngOnChanges(changes: SimpleChanges) {
if (changes['html'] && !changes['html'].isFirstChange()) {
this.dynamicComponent = this.createNewComponent(this.html);
this.dynamicModule = this.compiler.compileModuleSync(this.createComponentModule(this.dynamicComponent));
}
}
ngOnInit() {
this.dynamicComponent = this.createNewComponent(this.html);
this.dynamicModule = this.compiler.compileModuleSync(this.createComponentModule(this.dynamicComponent));
}
protected createComponentModule(componentType: any) {
@NgModule({
imports: [SharedModule],
declarations: [
componentType
],
entryComponents: [
componentType
],
})
class RuntimeComponentModule {
}
// a module for just this Type
return RuntimeComponentModule;
}
protected createNewComponent(template: string) {
@Component({
selector: 'dynamic-component',
template: template ? template : ''
})
class MyDynamicComponent {
}
return MyDynamicComponent;
}
}
The component is created in other component html templates like this:
<dynamic [html]="variableWithSomeHTML" routeTransformer></dynamic>
I'm using "npm start" which runs a script that looks like this: SET NODE_ENV=development && webpack serve --config config/webpack.dev.js --hot --progress --port 8080
But on compilation I get two errors:
ERROR in app/shared/dyanmicComponent/dynamic.component.ts:31:37 - error NG1010: Value at position 0 in the NgModule.declaratio
Value is a reference to 'componentType'.
31 protected createComponentModule(componentType: any) {
~~~~~~~~~~~~~~~~~~
app/shared/dyanmicComponent/dynamic.component.ts:31:37
31 protected createComponentModule(componentType: any) {
any) {
~~~~~~~~~~~~~
Reference is declared here.
ERROR in app/shared/dyanmicComponent/dynamic.component.ts:51:23 - error NG1010: template must be a string
Value is a reference to 'template'.
51 template: template ? template : ''
~~~~~~~~~~~~~~~~~~~~~~~~
app/shared/dyanmicComponent/dynamic.component.ts:47:34
47 protected createNewComponent(template: string) {
~~~~~~~~
Reference is declared here.
I'm hoping someone smart that knows Angular and dynamic components better than me can help me out here. Is there a fix to this or do I need to rewrite the way the dynamic components are created?
I have read on other posts that creating the template dynamically like this with a string variable is not possible. But I haven't found what it is in updating Angular from 12 to 13 that breaks this, as it used to compile just fine before updating.
I expect to either find some configuration that lets me compile components like this, or I have to rewrite how the dynamic components are created.