import { Component, ComponentFactoryResolver, Type, ViewChild, ViewContainerRef } from '@angular/core'; import { Observable } from 'rxjs/Observable'; import { DialogWrapperComponent } from './dialog-wrapper.component'; import { DialogComponent } from './dialog.component'; import { DialogOptions } from './dialog.service'; @Component({ selector: 'dialog-holder', template: '', }) export class DialogHolderComponent { /** * Target element to insert dialogs */ @ViewChild('element', {read: ViewContainerRef}) public element: ViewContainerRef; /** * Array of dialogs * @type {Array } */ dialogs: Array> = []; /** * Constructor * @param {ComponentFactoryResolver} resolver */ constructor(private resolver: ComponentFactoryResolver) {} /** * Adds dialog * @param {Type} component * @param {object?} data * @param {DialogOptions?} options * @return {Observable<*>} */ addDialog(component:Type>, data?:T, options?:DialogOptions):Observable { options = options || {}; let factory = this.resolver.resolveComponentFactory(DialogWrapperComponent); let componentRef = this.element.createComponent(factory, options.index); let dialogWrapper: DialogWrapperComponent = componentRef.instance; let _component: DialogComponent = dialogWrapper.addComponent(component); if(typeof(options.index) !== 'undefined') { this.dialogs.splice(options.index, 0, _component); } else { this.dialogs.push(_component); } setTimeout(()=>{ dialogWrapper.container.nativeElement.classList.add('show'); dialogWrapper.container.nativeElement.classList.add('in'); }); if(options.autoCloseTimeout) { setTimeout(()=>{ this.removeDialog(_component); }, options.autoCloseTimeout); } if(options.closeByClickingOutside) { dialogWrapper.closeByClickOutside(); } if(options.backdropColor) { dialogWrapper.container.nativeElement.style.backgroundColor = options.backdropColor; } this.updateBodyClass(); return _component.fillData(data); } /** * Removes dialog * @param {DialogComponent} component */ removeDialog(component:DialogComponent) { let element = component.wrapper.container.nativeElement; element.classList.remove('show'); element.classList.remove('in'); setTimeout(() => { this._removeElement(component); }, 300); } /** * Bind a body class 'modal-open' to a condition of dialogs in pool > 0 */ private updateBodyClass() { const bodyClass = 'modal-open'; const body = document.getElementsByTagName('body')[0]; if(!this.dialogs.length) { body.classList.remove(bodyClass); } else { body.classList.add(bodyClass); } } private _removeElement(component) { let index = this.dialogs.indexOf(component); if(index>-1) { this.element.remove(index); this.dialogs.splice(index, 1); } this.updateBodyClass(); } clear() { this.element.clear(); this.dialogs = []; } }