import { ComponentRef, Injectable, Injector, Type, ViewContainerRef } from "@angular/core"; import { first } from "rxjs/operators"; import { DynamicModalComponent } from "../components/modal/dynamic-modal.component"; import { ModalInjector } from "../components/modal/modal-injector"; import { ModalRef } from "../components/modal/modal.ref"; /** * @deprecated Use the Component Library's `DialogService` instead. */ @Injectable() export class ModalService { protected modalList: ComponentRef[] = []; constructor(private injector: Injector) { document.addEventListener("keyup", (event) => { if (event.key === "Escape" && this.modalCount > 0) { this.topModal.instance.close(); } }); } get modalCount() { return this.modalList.length; } private get topModal() { return this.modalList[this.modalCount - 1]; } /** * @deprecated Use `dialogService.open` instead. * If replacing an existing call to this method, also remove any `@ViewChild` and `` associated with the * existing usage. */ async openViewRef( componentType: Type, viewContainerRef: ViewContainerRef, setComponentParameters: (component: T) => void = null, ): Promise<[ModalRef, T]> { const [modalRef, modalComponentRef] = this.openInternal(viewContainerRef, componentType); modalComponentRef.instance.setComponentParameters = setComponentParameters; viewContainerRef.insert(modalComponentRef.hostView); await modalRef.onCreated.pipe(first()).toPromise(); return [modalRef, modalComponentRef.instance.componentRef.instance]; } closeAll(): void { this.modalList.forEach((modal) => modal.instance.close()); } protected openInternal( viewContainerRef: ViewContainerRef, componentType: Type, ): [ModalRef, ComponentRef] { const [modalRef, componentRef] = this.createModalComponent(viewContainerRef); componentRef.instance.childComponentType = componentType; modalRef.onClosed.pipe(first()).subscribe(() => { componentRef.destroy(); this.modalList.pop(); if (this.modalCount > 0) { this.topModal.instance.getFocus(); } }); this.setupHandlers(modalRef); this.modalList.push(componentRef); return [modalRef, componentRef]; } protected setupHandlers(modalRef: ModalRef) { let backdrop: HTMLElement = null; // Add backdrop, setup [data-dismiss] handler. modalRef.onCreated.pipe(first()).subscribe((el) => { document.body.classList.add("modal-open"); const modalEl: HTMLElement = el.querySelector(".modal"); const dialogEl = modalEl.querySelector(".modal-dialog") as HTMLElement; backdrop = document.createElement("div"); backdrop.className = "modal-backdrop fade"; backdrop.style.zIndex = `${this.modalCount}040`; modalEl.prepend(backdrop); dialogEl.addEventListener("click", (e: Event) => { e.stopPropagation(); }); dialogEl.style.zIndex = `${this.modalCount}050`; const modals = Array.from( el.querySelectorAll('.modal-backdrop, .modal *[data-dismiss="modal"]'), ); for (const closeElement of modals) { closeElement.addEventListener("click", () => { modalRef.close(); }); } }); // onClose is used in Web to hook into bootstrap. On other projects we pipe it directly to closed. modalRef.onClose.pipe(first()).subscribe(() => { modalRef.closed(); if (this.modalCount === 0) { document.body.classList.remove("modal-open"); } }); } protected createModalComponent( viewContainerRef: ViewContainerRef, ): [ModalRef, ComponentRef] { const modalRef = new ModalRef(); const map = new WeakMap(); map.set(ModalRef, modalRef); const injector = new ModalInjector(this.injector, map); const componentRef = viewContainerRef.createComponent(DynamicModalComponent, { injector }); return [modalRef, componentRef]; } }