Right click context menu with Angular

Updated: 2024-01-04

Update: I updated the source code for Angular 17 and for a Standalone component. The StackBlitz example is still based on Angular 10.

Create a right click context menu inside a dynamic list or table

GitHub demo

We need to link each element of a list or table to a right-click context mat-menu.

The list elements and their menu are generated only at runtime. To generate dynamically the menu we create a hidden div with the coordinates of the mouse.

Component code

Here is important to notice that we define the position of the menu using the coordinates of the mouse.

  // we create an object that contains coordinates 
menuTopLeftPosition =  {x: 0, y: 0}; 
 
// reference to the MatMenuTrigger in the DOM 
@ViewChild(MatMenuTrigger, {static: true}) matMenuTrigger!: MatMenuTrigger; 
 
/** 
 * Method called when the user click with the right button 
 * @param event MouseEvent, it contains the coordinates 
 * @param item Our data contained in the row of the table 
 */ 
onRightClick(event: MouseEvent, item: {content: string}): void { 
 
  // preventDefault avoids to show the visualization of the right-click menu of the browser 
  event.preventDefault(); 
 
  // we record the mouse position in our object 
  this.menuTopLeftPosition.x = event.clientX; 
  this.menuTopLeftPosition.y = event.clientY; 
 
  // we open the menu 
  // we pass to the menu the information about our object 
  this.matMenuTrigger.menuData = {item: item}; 
 
  // we open the menu 
  this.matMenuTrigger.openMenu(); 
 
} 

html code updated for Angular 17

<div class="container"> 
  <!-- we generate a number of items dynamically--> 
  @for(menuItem of getExamples(10); track menuItem) { 
  <div> 
    <!-- when the user clicks on the div the onRightClick event is called, we pass a simple object--> 
    <div (contextmenu)="onRightClick($event, {content: 'Item generated #' + menuItem})" 
         style="padding-bottom: 20px;"> 
      Item {{menuItem}} 
    </div> 
  </div> 
  } 
 
  <!-- a hidden div is created to set the position of appearance of the menu--> 
  <div 
          style="visibility: hidden; position: fixed;" 
          [style.left.px]="menuTopLeftPosition.x" 
          [style.top.px]="menuTopLeftPosition.y" 
          [matMenuTriggerFor]="rightMenu"></div> 
 
  <!-- standard material menu --> 
  <mat-menu #rightMenu="matMenu"> 
    <ng-template matMenuContent let-item="item"> 
      <button mat-menu-item>Clicked {{item.content}}</button> 
      <button mat-menu-item>Fixed menu</button> 
    </ng-template> 
  </mat-menu> 
</div> 

Here you can play the StackBlitz project


WebApp built by Marco using SpringBoot 3.2.4 and Java 21, in a Server in Switzerland without 'Cloud'.