-
-
Save benjamincharity/8116414c7f38cffe3cef0e44fe44295d to your computer and use it in GitHub Desktop.
import { | |
Component, | |
Directive, | |
NgModule, | |
Input, | |
ViewContainerRef, | |
Compiler, | |
ComponentFactory, | |
ModuleWithComponentFactories, | |
ComponentRef, | |
ReflectiveInjector | |
} from '@angular/core'; | |
import { RouterModule } from '@angular/router'; | |
import { CommonModule } from '@angular/common'; | |
export function createComponentFactory(compiler: Compiler, metadata: Component): Promise<ComponentFactory<any>> { | |
const cmpClass = class DynamicComponent {}; | |
const decoratedCmp = Component(metadata)(cmpClass); | |
@NgModule({ imports: [CommonModule, RouterModule], declarations: [decoratedCmp] }) | |
class DynamicHtmlModule { } | |
return compiler.compileModuleAndAllComponentsAsync(DynamicHtmlModule) | |
.then((moduleWithComponentFactory: ModuleWithComponentFactories<any>) => { | |
return moduleWithComponentFactory.componentFactories | |
.find(x => x.componentType === decoratedCmp); | |
}); | |
} | |
@Directive({ | |
selector: 'client-html-outlet', | |
}) | |
export class ClientHtmlOutletDirective { | |
@Input() html: string; | |
cmpRef: ComponentRef<any>; | |
constructor(private vcRef: ViewContainerRef, private compiler: Compiler) { } | |
ngOnChanges() { | |
const html = this.html; | |
if (!html) return; | |
if (this.cmpRef) { | |
this.cmpRef.destroy(); | |
} | |
const compMetadata = new Component({ | |
selector: 'dynamic-html', | |
template: this.html, | |
}); | |
createComponentFactory(this.compiler, compMetadata).then(factory => { | |
const injector = ReflectiveInjector.fromResolvedProviders([], this.vcRef.parentInjector); | |
this.cmpRef = this.vcRef.createComponent(factory, 0, injector, []); | |
}); | |
} | |
ngOnDestroy() { | |
if (this.cmpRef) { | |
this.cmpRef.destroy(); | |
} | |
} | |
} |
Sorry, I never saw this comment..
I haven't had the need for dynamic component generation in quite some time so I'm a bit outdated on this side of things. Possibly something like this could work. https://stackoverflow.com/a/49038739/722367 … Basically use the reference once you create the component to dynamically add methods/functionality
Hi Benjamin
I use your html outlet directive in my project.
Thank you a lot for this!Could you please explain me one thing
If dynamic html will contain some methods
<a (click)='onClick()'>homeDo I have possibility to predefine and describe this method somewhere in APP?
Thanks!
See my updated code here
inside the dynamic html you can pass an event trigger string back to the parent component to throw into a switch in order to control the behaviour
inside the dynamic html use
(click)="genEmit('pass back to parent')
inside the parent that holds the outlet
you can capture the emitted event
<html-outlet [html]="tableHTMLOutput" (genericEmitter)="captureEvent($event)" ></html-outlet>
I'm trying to use your directive to include a mvc partial view in my angular. But it doesn't work with Angular 10. Any Idea what's wrong?
Hi Benjamin
I use your html outlet directive in my project.
Thank you a lot for this!
Could you please explain me one thing
If dynamic html will contain some methods
<a (click)='onClick()'>home
Do I have possibility to predefine and describe this method somewhere in APP?
Thanks!