import { Injectable, ComponentFactoryResolver, ApplicationRef, Injector, Type, EmbeddedViewRef, ComponentRef } from '@angular/core'; import { DynamicDialogComponent } from './dynamicdialog'; import { DynamicDialogInjector } from './dynamicdialog-injector'; import { DynamicDialogConfig } from './dynamicdialog-config'; import { DynamicDialogRef } from './dynamicdialog-ref'; @Injectable() export class DialogService { dialogComponentRef: ComponentRef; constructor(private componentFactoryResolver: ComponentFactoryResolver, private appRef: ApplicationRef, private injector: Injector) { } public open(componentType: Type, config: DynamicDialogConfig) { const dialogRef = this.appendDialogComponentToBody(config); this.dialogComponentRef.instance.childComponentType = componentType; return dialogRef; } private appendDialogComponentToBody(config: DynamicDialogConfig) { const map = new WeakMap(); map.set(DynamicDialogConfig, config); const dialogRef = new DynamicDialogRef(); map.set(DynamicDialogRef, dialogRef); const sub = dialogRef.onClose.subscribe(() => { this.dialogComponentRef.instance.close(); }); const destroySub = dialogRef.onDestroy.subscribe(() => { this.removeDialogComponentFromBody(); destroySub.unsubscribe(); sub.unsubscribe(); }); const componentFactory = this.componentFactoryResolver.resolveComponentFactory(DynamicDialogComponent); const componentRef = componentFactory.create(new DynamicDialogInjector(this.injector, map)); this.appRef.attachView(componentRef.hostView); const domElem = (componentRef.hostView as EmbeddedViewRef).rootNodes[0] as HTMLElement; document.body.appendChild(domElem); this.dialogComponentRef = componentRef; return dialogRef; } private removeDialogComponentFromBody() { this.appRef.detachView(this.dialogComponentRef.hostView); this.dialogComponentRef.destroy(); } }