Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using mat-menu as a context menu: getting the positioning right

I'm trying to build a context menu using mat-menu, and I feel like I'm pretty close. I want the menu to pop-up where the user right-clicks. The problem is that it's popping up where the user last right-clicked, not where they currently right-clicked. How do I fix this?

HTML:

<span #contextMenuTrigger [matMenuTriggerFor]="contextMenu" class="context-menu-trigger" [style.left.px]="menuLeft" [style.top.px]="menuTop"></span>
<div (contextmenu)="openContextMenu($event)> stuff that I want right-click available to goes here</div>
<mat-menu #contextMenu="matMenu"> 
    <button mat-menu-item>Item 1</button>
    <button mat-menu-item>Item 2</button>
</mat-menu>

CSS:

.context-menu-trigger { position: absolute }

TS:

...
@Component( ... )
export class AppComponent {
    @ViewChild(MatMenuTrigger) public menuTrigger : MatMenuTrigger;
    public menuLeft = 0;
    public menuTop = 0;
    ...
    openContextMenu(event) {
        event.preventDefault();
        this.menuLeft = event.x;
        this.menuTop = event.y;
        this.menuTrigger.openMenu();
    }
}

We are currently on @angular 4.4 and @angular/material 2.0.0-beta.12.

like image 794
afeygin Avatar asked Jan 23 '18 22:01

afeygin


1 Answers

It's not safe to rely on timeout. Set direct style for your span trigger to get instant position update:

<span style="position:fixed;" #spanTrigger class="context-menu-trigger" #matTrigger="matMenuTrigger" [matMenuTriggerFor]="contextMenu"></span>
<div (contextmenu)="openContextMenu($event, matTrigger, spanTrigger)> stuff that I want right-click available to goes here</div>
<mat-menu #contextMenu="matMenu"> 
    <button mat-menu-item>Item 1</button>
    <button mat-menu-item>Item 2</button>
</mat-menu>

Handler:

 openContextMenu(
    event: MouseEvent,
    trigger: MatMenuTrigger,
    triggerElement: HTMLElement
  ) {
    triggerElement.style.left = event.clientX + 5 + "px";
    triggerElement.style.top = event.clientY + 5 + "px";
    if (trigger.menuOpen) {
      trigger.closeMenu();
      trigger.openMenu();
    } else {
      trigger.openMenu();
    }
    event.preventDefault();
  }
like image 93
Ievgen Avatar answered Oct 05 '22 23:10

Ievgen