diff --git a/src/components/angular2-modal/models/dialog-ref-stack.ts b/src/components/angular2-modal/models/dialog-ref-stack.ts index bdcc9dfa..8f293091 100644 --- a/src/components/angular2-modal/models/dialog-ref-stack.ts +++ b/src/components/angular2-modal/models/dialog-ref-stack.ts @@ -1,49 +1,91 @@ import { DialogRef } from './dialog-ref'; +const BASKET_GROUP = {}; + /** * A dumb stack implementation over an array. */ export class DialogRefStack { - private _stack: DialogRef[] = []; + private _stack: DialogRef[]; + private _stackMap: Map, any>; + get length(): number { + return this._stack.length; + } - push(dialogRef: DialogRef): void { - let idx = this._stack.indexOf(dialogRef); - if (idx === -1) this._stack.push(dialogRef); - } + constructor() { + this._stack = []; + this._stackMap = new Map, any>(); + } - /** - * Push a DialogRef into the stack and manage it so when it's done - * it will automatically kick itself out of the stack. - * @param dialogRef - */ - pushManaged(dialogRef: DialogRef): void { - this.push(dialogRef); + push(dialogRef: DialogRef, group?: any): void { + if (this._stack.indexOf(dialogRef) === -1) { + this._stack.push(dialogRef); + this._stackMap.set(dialogRef, group || BASKET_GROUP); } + } - pop(): void { - this._stack.pop(); - } + /** + * Push a DialogRef into the stack and manage it so when it's done + * it will automatically kick itself out of the stack. + * @param dialogRef + */ + pushManaged(dialogRef: DialogRef, group?: any): void { + this.push(dialogRef, group); + dialogRef.onDestroy.subscribe(() => this.remove(dialogRef)); + } - /** - * Remove a DialogRef from the stack. - * @param dialogRef - */ - remove(dialogRef: DialogRef): void { - let idx = this._stack.indexOf(dialogRef); - if (idx > -1) this._stack.splice(idx, 1); + pop(): DialogRef { + const dialogRef = this._stack.pop(); + this._stackMap.delete(dialogRef); + return dialogRef; + } + + /** + * Remove a DialogRef from the stack. + * @param dialogRef + */ + remove(dialogRef: DialogRef): void { + let idx = this.indexOf(dialogRef); + if (idx > -1) { + this._stack.splice(idx, 1); + this._stackMap.delete(dialogRef); } + } + index(index: number): DialogRef { + return this._stack[index]; + } - index(index: number): DialogRef { - return this._stack[index]; - } + indexOf(dialogRef: DialogRef): number { + return this._stack.indexOf(dialogRef); + } + + groupOf(dialogRef: DialogRef): any { + return this._stackMap.get(dialogRef); + } - indexOf(dialogRef: DialogRef): number { - return this._stack.indexOf(dialogRef); + groupBy(group: any): DialogRef[] { + let arr = []; + if (group) { + this._stackMap.forEach( (value, key) => { + if (value === group) { + arr.push(key); + } + }); } + return arr; + } - get length(): number { - return this._stack.length; + groupLength(group: any): number { + let count = 0; + if (group) { + this._stackMap.forEach( (value, key) => { + if (value === group) { + count++; + } + }); } + return count; + } } diff --git a/src/components/angular2-modal/models/dialog-ref.ts b/src/components/angular2-modal/models/dialog-ref.ts index c62a607f..76f7d896 100644 --- a/src/components/angular2-modal/models/dialog-ref.ts +++ b/src/components/angular2-modal/models/dialog-ref.ts @@ -102,20 +102,23 @@ export class DialogRef { destroy() { if (this.destroyed !== true) { this.destroyed = true; - this._onDestroy.next(null); - - this._onDestroy.complete(); if (typeof this.overlayRef.instance.canDestroy === 'function') { this.overlayRef.instance.canDestroy() .catch( () => {}) - .then ( () => this.overlayRef.destroy() ); + .then ( () => this._destroy() ); } else { - this.overlayRef.destroy(); + this._destroy(); } } } + private _destroy(): void { + this._onDestroy.next(null); + this._onDestroy.complete(); + this.overlayRef.destroy() + } + private _fireHook(name: 'beforeClose' | 'beforeDismiss'): Promise { const gurad = this.closeGuard, fn: Function = gurad && typeof gurad[name] === 'function' && gurad[name]; diff --git a/src/components/angular2-modal/overlay/overlay.service.ts b/src/components/angular2-modal/overlay/overlay.service.ts index e6f62832..3572f60c 100644 --- a/src/components/angular2-modal/overlay/overlay.service.ts +++ b/src/components/angular2-modal/overlay/overlay.service.ts @@ -39,11 +39,18 @@ export class Overlay { return _stack.indexOf(dialogRef); } + groupStackLength(dialogRef: DialogRef): number { + return _stack.groupLength(_stack.groupOf(dialogRef)); + } + /** - * Opens a modal window inside an existing component. + * Creates an overlay and returns a dialog ref. + * @param config instructions how to create the overlay + * @param group A token to associate the new overlay with, used for reference (stacks usually) + * @returns {DialogRef[]} */ - open(config: OverlayConfig): DialogRef[] { + open(config: OverlayConfig, group?: any): DialogRef[] { let viewContainer = config.viewContainer, containers: Array = []; @@ -62,12 +69,14 @@ export class Overlay { containers = [this.defaultViewContainer]; } - return containers.map( vc => this.createOverlay(config.renderer || this._modalRenderer, vc, config)); + return containers + .map( vc => this.createOverlay(config.renderer || this._modalRenderer, vc, config, group)); } private createOverlay(renderer: OverlayRenderer, vcRef: ViewContainerRef, - config: OverlayConfig): DialogRef { + config: OverlayConfig, + group: any): DialogRef { if (config.context) { config.context.normalize(); } @@ -78,8 +87,7 @@ export class Overlay { let cmpRef = renderer.render(dialog, vcRef); Object.defineProperty(dialog, 'overlayRef', {value: cmpRef}); - _stack.pushManaged(dialog); - dialog.onDestroy.subscribe(() => _stack.remove(dialog)); + _stack.pushManaged(dialog, group); return dialog; } diff --git a/src/components/angular2-modal/providers/modal.ts b/src/components/angular2-modal/providers/modal.ts index f62b63ce..a7ec01d1 100644 --- a/src/components/angular2-modal/providers/modal.ts +++ b/src/components/angular2-modal/providers/modal.ts @@ -42,7 +42,7 @@ export abstract class Modal { open(componentType: any, config?: OverlayConfig): Promise> { config = config || {} as any; try { - let dialogs = this.overlay.open(config); + let dialogs = this.overlay.open(config, this.constructor); if (dialogs.length > 1) { console.warn(`Attempt to open more then 1 overlay detected.