I'm using MatMenu as a popup to tour around new users on my web app so I don't want to dismiss it whenever the user clicks outside of it.
I've already used used $event.stopPropagation() to stop it from closing when I click a button inside it. Now I want to know how to keep it open even if you click outside of it.
The click is handled by the overlay backdrop. You can apply/remove classes to the backdrop dynamically based on your menu open and close, and defeat the backdrop click using CSS withpointer-events .
For example:
HTML
<button mat-button [matMenuTriggerFor]="menu" (menuOpened)="preventCloseOnClickOut()" (menuClosed)="allowCloseOnClickOut()">Menu</button>
TS
export class MenuOverviewExample {
constructor(private overlayContainer: OverlayContainer) {}
preventCloseOnClickOut() {
this.overlayContainer.getContainerElement().classList.add('disable-backdrop-click');
}
allowCloseOnClickOut() {
this.overlayContainer.getContainerElement().classList.remove('disable-backdrop-click');
}
}
Global CSS
.disable-backdrop-click .cdk-overlay-backdrop.cdk-overlay-transparent-backdrop.cdk-overlay-backdrop-showing {
pointer-events: none;
}
i think [hasBackdrop]="false" and [hasBackdrop]="true" can handle that
You can wrap around the mat-menu-items if you are trying to stop propagating the whole menu.
<mat-menu [hasBackdrop]="false">
<div (click)="$event.stopPropagation()" (keydown)="$event.stopPropagation()">
<your-app></your-app>
</div>
</mat-menu>
I had the same problem, I had need a validation and as result the outside click (on backdrop) shouldn't effect. Remove the backdrop events with pointer-events allows interactions in all behind element, my solution was create a clone of backdrop and remove the listeners of this clone.
avoidClickOutside() {
const overlayers = this.overlay
.getContainerElement()
.querySelectorAll('.controlled');
if (overlayers && this.isAvoidClickOutside) {
overlayers.forEach((element) => {
const clone = element.cloneNode(true);
(clone as Element).classList.add('clone');
clone.addEventListener('click', (event: Event) => {
if (confirm('Not allowed... Do you want remove this behaviour?!')) {
this.removeCloneBackdrop();
}
});
element.parentNode.insertBefore(clone, element.nextSibling);
});
}
}
isAvoidClickOutside is my control variable to either avoid or not.
Available: https://stackblitz.com/edit/angular-yjvkft
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.