import { ComponentFactoryResolver, Injector, ApplicationRef, Injectable, EmbeddedViewRef, } from '@angular/core'; @Injectable() export default class ContextMenuService { private curComponentRef: any; constructor( private componentFactoryResolver: ComponentFactoryResolver, private appRef: ApplicationRef, private injector: Injector) { } show(component: any, args: any = {}) { if (this.curComponentRef) { this.close(this.curComponentRef); } // 1. Create a component reference from the component const componentRef = this.componentFactoryResolver.resolveComponentFactory(component).create(this.injector); // 2. Attach component to the appRef so that it's inside the ng component tree this.appRef.attachView(componentRef.hostView); // 3. Get DOM element from component const domElem = (componentRef.hostView as EmbeddedViewRef).rootNodes[0] as HTMLElement; // 4. Append DOM element to the body document.body.appendChild(domElem); this.curComponentRef = componentRef; componentRef.instance['context'] = { ...args, close: ev => { //5. remove it from the component tree and from the DOM this.close(componentRef); } } } close(componentRef) { //5. remove it from the component tree and from the DOM this.appRef.detachView(componentRef.hostView); componentRef.destroy(); this.curComponentRef = null; } }