Issue
I want to implement basic dialog handling in my application, with 2 functions:
- To close all open dialogs: Easy with MatDialog.closeAll();
- Enable the user to switch between open dialogs!
This is a problem for me, because it seems like there is no function to make a dialog the first one in order.
I can query all the open dialogs with MatDialog.openDialogs, and I can display the name of them for the user to chose from. After that i tried to add a panel class to the clicked one which modifies the z-index, but nothing happened.
What could be the solution?
My code:
HTML template for the menu, to handle dialog actions:
<mat-menu #menu="matMenu">
<button mat-menu-item (click)="closeAll()">
<mat-icon>close_all</mat-icon>
<span>Close all</span>
</button>
<mat-divider></mat-divider>
<button
(click)="focusDialog(dialog, $event)"
*ngFor="let dialog of this.dialog.openDialogs"
mat-menu-item
>
<mat-icon>preview</mat-icon>
<span>{{ dialog.componentInstance.data.title }}</span>
</button>
</mat-menu>
Button click event handler:
focusDialog(dialogRef: MatDialogRef<any>, e: any) {
e.stopPropagation();
this.dialog.openDialogs.forEach((dialog) => {
dialog.removePanelClass('dialog-focus');
});
dialogRef.addPanelClass('dialog-focus');
}
dialog-focus css class:
.dialog-focus .mat-dialog-container{
z-index: 1000 !important;
}
EDIT:
I couldn't seem to achive anyhting with z-index, but i could set the display of the dialogs to 'block' or 'none' and this way, i could see the preferred dialog. The problem is: I can not interact with it! The overlay of the lastly opened dialog is still there. How could I make it disappear, and then use it again if the usert switches back to its related dialog?
focusDialog(dialogRef: MatDialogRef<any>, e: any) {
e.stopPropagation();
this.dialog.openDialogs.forEach((dialog) => {
dialog.removePanelClass('dialog-focus');
dialog.addPanelClass('dialog-background');
});
dialogRef.addPanelClass('dialog-focus');
dialogRef.removePanelClass('dialog-background');
}
.dialog-focus .mat-dialog-container {
z-index: 1000 !important;
display: block;
}
.dialog-background .mat-dialog-container {
z-index: 1 !important;
display: none;
}
I inspected the HTML Tree and seems like the opened dialogs and the overlays are siblings.
Solution
Based on Eliseo's answer I came up with another solution, which fits my application better:
I did't want the parent component to manage the overlay order change, because I think it's more universal, if I create a component which is responsible for all dialog actions, and accepts a component as input to load it's template inside it's self. This way I can open a dilaog easily anywhere in my app, and open dialogs inside dialogs so on.
Based on Eliseo's answer, no panel class modification needed. Reordering the cdk-global-overlay-wrapper elements is enough.
Stackblitz link for the solution:
How the files in the original question changed:
HTML
<mat-menu #menu="matMenu">
<button mat-menu-item (click)="closeAll()">
<mat-icon>close_all</mat-icon>
<span>Close all</span>
</button>
<mat-divider></mat-divider>
<button
(click)="focusDialog(dialog, $event)"
*ngFor="let dialog of this.dialog.openDialogs"
mat-menu-item
>
<mat-icon>preview</mat-icon>
<span>{{ dialog.componentInstance.data.title }}</span>
</button>
</mat-menu>
focusDialog(dialogRef: MatDialogRef<any>, e: any) {
const cdkOverlayWrappers = document.getElementsByClassName(
'cdk-global-overlay-wrapper'
);
for (let i = 0; i < cdkOverlayWrappers.length; i++) {
const wrapper = cdkOverlayWrappers[i];
if (wrapper.contains(dialogRef.componentInstance.el.nativeElement)) {
const parent = wrapper.parentNode!;
const last = parent.lastChild;
if (last != wrapper)
last!.parentNode!.insertBefore(wrapper, last!.nextSibling);
break;
}
}
}
Answered By - eogabor
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.