角度:v8.2.8
我设法使用mat-menu(角度材质)来模拟上下文菜单。无论如何,右键单击我的页面,菜单就会出现在我的鼠标位置。
我要实现的目标:将鼠标移到页面上的其他位置时,再次单击鼠标右键。我期望菜单在原始位置关闭,然后在新位置重新打开。
但是实际上::当我右键单击时,什么也没有发生,并且原始位置的菜单保持打开状态。
事实上,我必须左键单击以在原始位置关闭打开的菜单,然后右键单击以在新的鼠标位置打开菜单。
问题:知道如何实现我想要的目标吗?
@Component({
selector: 'fl-home',
template:`
<mat-menu #contextmenu>
<div >
<button mat-menu-item>Clear all Paths</button>
</div>
</mat-menu>
<div [matMenuTriggerFor]="contextmenu" [style.position]="'absolute'" [style.left.px]="menuX" [style.top.px]="menuY" ></div>
<div class="container" (contextmenu)="onTriggerContextMenu($event);"> ....</div>
`})
export class HomeComponent {
menuX:number=0
menuY:number=0
@ViewChild(MatMenuTrigger,{static:false}) menu: MatMenuTrigger;
onTriggerContextMenu(event){
event.preventDefault();
this.menuX = event.x - 10;
this.menuY = event.y - 10;
this.menu.closeMenu() // close existing menu first.
this.menu.openMenu()
}
}
答案 0 :(得分:1)
我的解决方案
ngOnInit(): void {
this.windowClickSubscription = fromEvent(window, 'click').subscribe((_) => {
if (this.contextMenu.menuOpen) {
this.contextMenu.closeMenu();
}
});
}
ngOnDestroy(): void {
this.windowClickSubscription && this.windowClickSubscription.unsubscribe();
this.menuSubscription && this.menuSubscription.unsubscribe();
}
onContextMenu(event: MouseEvent){
event.preventDefault();
this.menuSubscription && this.menuSubscription.unsubscribe();
this.menuSubscription = of(1)
.pipe(
tap(() => {
if (this.contextMenu.menuOpen) {
this.contextMenu.closeMenu();
}
this.contextMenuPosition.x = event.clientX;
this.contextMenuPosition.y = event.clientY;
}),
// delay(this.contextMenu.menuOpen ? 200 : 0),
delayWhen((_) => (this.contextMenu.menuOpen ? interval(200) : of(undefined))),
tap(async() => {
this.contextMenu.openMenu();
let backdrop: HTMLElement = null;
do {
await this.delay(100);
backdrop = document.querySelector(
'div.cdk-overlay-backdrop.cdk-overlay-transparent-backdrop.cdk-overlay-backdrop-showing'
) as HTMLElement;
} while (backdrop === null);
backdrop.style.pointerEvents = 'none';
})
)
.subscribe();
}
delay(delayInms: number) {
return new Promise((resolve) => {
setTimeout(() => {
resolve(2);
}, delayInms);
});
}
答案 1 :(得分:0)
只需添加hasBackdrop = false即可。 发生的情况是,当我右键单击菜单后打开菜单时,将出现一个不可见的背景覆盖,覆盖整个页面。难怪无论我如何再次尝试右键单击,contextmenu事件都不会触发,因此不会调用onTriggerContextMenu()。通过将hasBackgrop设置为false,该覆盖图将不会显示。
答案 2 :(得分:0)
也许您已经解决了,但是对于其他人,这是我解决此问题的方法: 环绕div中的菜单项,当鼠标离开菜单(该div)时,我将其关闭,因此您可以立即再次右键单击另一个位置以再次显示上下文菜单...。
<div (mouseleave)="mouseLeaveMenu()">
...menu items...
</div>
...
mouseLeaveMenu() {
if (this.contextMenu.menuOpened) this.contextMenu.closeMenu();
}
答案 3 :(得分:0)
[hasBackdrop]="false"
添加到mat-menu
onTriggerContextMenu()
函数更新为如下所示(contextmenu)="..."
触发器的位置也添加(click)="themenu.closeMenu();"
onTriggerContextMenu(event: MouseEvent) {
this.themenu.closeMenu();
event.preventDefault();
this.menuX = event.clientX;
this.menuY = event.clientY;
this.themenu.menu.focusFirstItem('mouse');
this.themenu.openMenu();
}
答案 4 :(得分:0)
如果您不想像大多数其他答案一样先关闭菜单,您可以手动设置菜单的位置:
// Assume you have the position in variables x and y
// Additionally you need to have the MatMenuTrigger (in this example in variable matMenuTrigger)
// this.cd.markForCheck() is important here if you just opened the menu with matMenuTrigger.openMenu()
const panelID = matMenuTrigger.menu.panelId;
const panelElement: HTMLElement = document.getElementById(panelID);
panelElement.style.position = "absolute";
panelElement.style.left = x + "px";
panelElement.style.top = y + "px";