I'm using a Angular Dynamic Compile component called P3X Angular Compile
, that turns a string into a compiled component in my nativescript project.
link : https://npm.taobao.org/package/p3x-angular-compile .
I install that via npm
in my {N} project but it did not work, so I use a part of P3X
's source code in my project and create a dynamic-component-builder
like this :
dynamic-component.ts:
export class DynamicComponentBuilder implements OnChanges {
@Input('template') html: string;
@Input('module') module: NgModule;
@Input('parent') context: any;
@Input('error-handler') errorHandler: Function = undefined;
@Input('imports') imports: Array<Type<any> | ModuleWithProviders | any[]>;
dynamicComponent: any;
dynamicModule: NgModuleFactory<any> | any;
constructor(private compiler: Compiler) { }
ngOnChanges(changes: SimpleChanges) {
this.update();
}
update() {
try {
if (this.html === undefined || this.html === null || this.html.trim() === '') {
this.dynamicComponent = undefined;
this.dynamicModule = undefined;
return;
}
this.dynamicComponent = this.createNewComponent(this.html, this.context);
this.dynamicModule = this.compiler.compileModuleSync(this.createComponentModule(this.dynamicComponent));
} catch (e) {
if (this.errorHandler === undefined)
throw e;
else
this.errorHandler(e);
}
}
createComponentModule(componentType: any) {
let module: NgModule = {};
if (this.module !== undefined)
module = cloneDeep(this.module);
module.imports = module.imports || [];
module.imports.push(CommonModule);
if (this.imports !== undefined)
module.imports = module.imports.concat(this.imports)
if (module.declarations === undefined)
module.declarations = [componentType];
else
module.declarations.push(componentType);
module.entryComponents = [componentType];
@NgModule(module)
class RuntimeComponentModule { }
return RuntimeComponentModule;
}
createNewComponent(html: string, context: any) {
@Component({
selector: nextId(),
template: html
})
class DynamicComponent {
context: any = context;
}
return DynamicComponent;
}
}
dynamic-component.html:
<ng-container *ngIf="html !== undefined && html !== null && html.trim() !=='' ">
<ng-container *ngComponentOutlet="dynamicComponent; ngModuleFactory:
dynamicModule;"> </ng-container>
</ng-container>
and I use this component like this:
customPage.html:
<StackLayout dynamic [template]="myListCmp" [module]="myListMd" [parent]="this"></StackLayout>
<StackLayout dynamic [template]="textField" [parent]="this"></StackLayout>
customPage.ts:
textField= "<TextField hint='Enter date'></TextField>";
myListCmp= "<my-list></my-list>";
myListMd= { entryComponents: [ MyListComponent ] }
the component work with textField
correctly but with my custom my-list
component not working and get the following errors:
ERROR Error: Can't compile synchronously as MyListComponent is still being loaded!
ERROR Error: No component factory found for DynamicComponent. Did you add it to @NgModule.entryComponents?
I need to mention that my-list
component is declared in a custom Module.
Please Help! thanks.