Skip to content

Commit

Permalink
feat: support stacks of a specific group (i.e: overlay stack per plugin)
Browse files Browse the repository at this point in the history
fix: change overlay destroy order, first run hooks, then observable then destroy overlay component ref
  • Loading branch information
Shlomi Assaf (shlassaf) committed Aug 23, 2016
1 parent 2c9bca5 commit 18acd51
Show file tree
Hide file tree
Showing 4 changed files with 94 additions and 41 deletions.
100 changes: 71 additions & 29 deletions 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<T> {
private _stack: DialogRef<T>[] = [];
private _stack: DialogRef<T>[];
private _stackMap: Map<DialogRef<T>, any>;

get length(): number {
return this._stack.length;
}

push(dialogRef: DialogRef<T>): void {
let idx = this._stack.indexOf(dialogRef);
if (idx === -1) this._stack.push(dialogRef);
}
constructor() {
this._stack = [];
this._stackMap = new Map<DialogRef<T>, 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<T>): void {
this.push(dialogRef);
push(dialogRef: DialogRef<T>, 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<T>, group?: any): void {
this.push(dialogRef, group);
dialogRef.onDestroy.subscribe(() => this.remove(dialogRef));
}

/**
* Remove a DialogRef from the stack.
* @param dialogRef
*/
remove(dialogRef: DialogRef<T>): void {
let idx = this._stack.indexOf(dialogRef);
if (idx > -1) this._stack.splice(idx, 1);
pop(): DialogRef<T> {
const dialogRef = this._stack.pop();
this._stackMap.delete(dialogRef);
return dialogRef;
}

/**
* Remove a DialogRef from the stack.
* @param dialogRef
*/
remove(dialogRef: DialogRef<T>): void {
let idx = this.indexOf(dialogRef);
if (idx > -1) {
this._stack.splice(idx, 1);
this._stackMap.delete(dialogRef);
}
}

index(index: number): DialogRef<T> {
return this._stack[index];
}

index(index: number): DialogRef<T> {
return this._stack[index];
}
indexOf(dialogRef: DialogRef<T>): number {
return this._stack.indexOf(dialogRef);
}

groupOf(dialogRef: DialogRef<T>): any {
return this._stackMap.get(dialogRef);
}

indexOf(dialogRef: DialogRef<T>): number {
return this._stack.indexOf(dialogRef);
groupBy(group: any): DialogRef<T>[] {
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;
}
}
13 changes: 8 additions & 5 deletions src/components/angular2-modal/models/dialog-ref.ts
Expand Up @@ -102,20 +102,23 @@ export class DialogRef<T> {
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<T>(name: 'beforeClose' | 'beforeDismiss'): Promise<T> {
const gurad = this.closeGuard,
fn: Function = gurad && typeof gurad[name] === 'function' && gurad[name];
Expand Down
20 changes: 14 additions & 6 deletions src/components/angular2-modal/overlay/overlay.service.ts
Expand Up @@ -39,11 +39,18 @@ export class Overlay {
return _stack.indexOf(dialogRef);
}

groupStackLength(dialogRef: DialogRef<any>): 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<T>[]}
*/
open<T extends OverlayContext>(config: OverlayConfig): DialogRef<T>[] {
open<T extends OverlayContext>(config: OverlayConfig, group?: any): DialogRef<T>[] {
let viewContainer = config.viewContainer,
containers: Array<ViewContainerRef> = [];

Expand All @@ -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<any> {
config: OverlayConfig,
group: any): DialogRef<any> {
if (config.context) {
config.context.normalize();
}
Expand All @@ -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;
}
Expand Down
2 changes: 1 addition & 1 deletion src/components/angular2-modal/providers/modal.ts
Expand Up @@ -42,7 +42,7 @@ export abstract class Modal {
open(componentType: any, config?: OverlayConfig): Promise<DialogRef<any>> {
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.
Expand Down

0 comments on commit 18acd51

Please sign in to comment.