Issue
I was tasked to update an Angular library from 7 to 13. This Library used Compiler and ComponentFactory to dynamically load Components. But those classes are now deprecated, and I found no real guide on how to do this without using these classes. Here's the code in question:
dynamic-content.component.ts:
...
private createCompiledTemplateFactory = (template: string, extensionType: string): ComponentFactory<any> | undefined => {
const metadata = {
selector: `dynamic-extended-component-${extensionType}`,
template: template
};
const extType = ClassInjector.get(extensionType);
if (!extType) {
throw new Error('Type not found: ' + extensionType);
}
return this.createComponentFactorySync(metadata, null, extType);
}
private createComponentFactorySync = (metadata: Component, componentClass: any, extensionType: Type<any>)
: ComponentFactory<any> | undefined => {
const cmpClass = componentClass || class RuntimeComponent extends extensionType { };
const decoratedCmp = Component(metadata)(cmpClass);
const externalImports = this.externalImports;
@NgModule({
imports: [
CommonModule,
FormsModule,
DynamicGridModule.forChild(),
DxButtonModule,
DxSwitchModule,
TranslateModule,
RouterModule,
externalImports,
DynamicPageCommonComponentsModule
],
declarations: [decoratedCmp]
})
class RuntimeComponentModule { }
const module: ModuleWithComponentFactories<any> = this.compiler.compileModuleAndAllComponentsSync(RuntimeComponentModule);
return module.componentFactories.find(f => f.componentType === decoratedCmp);
}
...
class-injector.ts
export class ClassInjector {
private static registry: { [key: string]: Type<any> } = {};
static register(key: string, value: Type<any>) {
const registered = ClassInjector.registry[key];
if (registered) {
throw new Error(`Error: ${key} is already registered.`);
}
ClassInjector.registry[key] = value;
}
static get(key: string): Type<any> {
const registered = ClassInjector.registry[key];
if (registered) {
return registered;
} else {
throw new Error(`Error: ${key} was not registered.`);
}
}
}
export function RegisterActionHandler(name: string) {
return (target: Type<any>) => ClassInjector.register(name, target);
}
I would appreciate it if anyone could guide me in the right direction.
Solution
We found out that the component could work without any mention of compiler:
dynamic-content.component.ts:
...
private createComponent = (template: string, extensionType: string) : Type<any> => {
const metadata = {
selector: `dynamic-extended-component-${extensionType}`,
template: template
};
const extType = ClassInjector.get(extensionType);
if (!extType) {
throw new Error('Type not found: ' + extensionType);
}
return Component(metadata)(class RuntimeComponent extends extType { });
}
private createModule = (component: Type<any>) : Type<any> => {
const externalImports = this.externalImports;
const module = NgModule({
imports: [
CommonModule,
FormsModule,
DynamicGridModule.forChild(),
DxButtonModule,
DxSwitchModule,
TranslateModule,
RouterModule,
externalImports,
DynamicPageCommonComponentsModule
],
declarations: [component]
})(
class RuntimeComponentModule { });
return module;
}
...
class-injector.ts stayed the same.
Answered By - tsavinho
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.