Menu

Overview for menu

<mat-menu> is a floating panel containing list of options.

Basic menu

By itself, the <mat-menu> element does not render anything. The menu is attached to and opened via application of the matMenuTriggerFor directive:

<mat-menu #appMenu="matMenu">
  <button mat-menu-item>Settings</button>
  <button mat-menu-item>Help</button>
</mat-menu>

<button mat-icon-button [matMenuTriggerFor]="appMenu">
  <mat-icon>more_vert</mat-icon>
</button>

The menu exposes an API to open/close programmatically. Please note that in this case, an matMenuTriggerFor directive is still necessary to attach the menu to a trigger element in the DOM.

class MyComponent {
  @ViewChild(MatMenuTrigger) trigger: MatMenuTrigger;

  someMethod() {
    this.trigger.openMenu();
  }
}

Menus support displaying mat-icon elements before the menu item text.

my-comp.html

<mat-menu #menu="matMenu">
  <button mat-menu-item>
    <mat-icon>dialpad</mat-icon>
    <span>Redial</span>
  </button>
  <button mat-menu-item disabled>
    <mat-icon>voicemail</mat-icon>
    <span>Check voicemail</span>
  </button>
  <button mat-menu-item>
    <mat-icon>notifications_off</mat-icon>
    <span>Disable alerts</span>
  </button>
</mat-menu>

By default, the menu will display below (y-axis), after (x-axis), and overlapping its trigger. The position can be changed using the xPosition (before | after) and yPosition (above | below) attributes. The menu can be be forced to not overlap the trigger using [overlapTrigger]="false" attribute.

<mat-menu #appMenu="matMenu" yPosition="above">
  <button mat-menu-item>Settings</button>
  <button mat-menu-item>Help</button>
</mat-menu>

<button mat-icon-button [matMenuTriggerFor]="appMenu">
  <mat-icon>more_vert</mat-icon>
</button>
Menu positioning

Material supports the ability for an mat-menu-item to open a sub-menu. To do so, you have to define your root menu and sub-menus, in addition to setting the [matMenuTriggerFor] on the mat-menu-item that should trigger the sub-menu:

<mat-menu #rootMenu="matMenu">
  <button mat-menu-item [matMenuTriggerFor]="subMenu">Power</button>
  <button mat-menu-item>System settings</button>
</mat-menu>

<mat-menu #subMenu="matMenu">
  <button mat-menu-item>Shut down</button>
  <button mat-menu-item>Restart</button>
  <button mat-menu-item>Hibernate</button>
</mat-menu>

<button mat-icon-button [matMenuTriggerFor]="rootMenu">
  <mat-icon>more_vert</mat-icon>
</button>
Nested menu

By default, the menu content will be initialized even when the panel is closed. To defer initialization until the menu is open, the content can be provided as an ng-template with the matMenuContent attribute:

<mat-menu #appMenu="matMenu">
  <ng-template matMenuContent>
    <button mat-menu-item>Settings</button>
    <button mat-menu-item>Help</button>
  </ng-template>
</mat-menu>

<button mat-icon-button [matMenuTriggerFor]="appMenu">
  <mat-icon>more_vert</mat-icon>
</button>

When using lazy rendering, additional context data can be passed to the menu panel via the matMenuTriggerData input. This allows for a single menu instance to be rendered with a different set of data, depending on the trigger that opened it:

<mat-menu #appMenu="matMenu">
  <ng-template matMenuContent let-name="name">
    <button mat-menu-item>Settings</button>
    <button mat-menu-item>Log off {{name}}</button>
  </ng-template>
</mat-menu>

<button mat-icon-button [matMenuTriggerFor]="appMenu" [matMenuTriggerData]="{name: 'Sally'}">
  <mat-icon>more_vert</mat-icon>
</button>

<button mat-icon-button [matMenuTriggerFor]="appMenu" [matMenuTriggerData]="{name: 'Bob'}">
  <mat-icon>more_vert</mat-icon>
</button>
  • DOWN_ARROW: Focuses the next menu item
  • UP_ARROW: Focuses previous menu item
  • RIGHT_ARROW: Opens the menu item's sub-menu
  • LEFT_ARROW: Closes the current menu, if it is a sub-menu.
  • ENTER: Activates the focused menu item

Menu triggers or menu items without text or labels should be given a meaningful label via aria-label or aria-labelledby.