How to open mat-menu programmatically?
If you want to completely control it programmatically, without having an element on your website that also controls the menu, you can declare an element containing [matMenuTriggerFor]
, but hiding it via CSS.
Caveat: You will have to manually position the menu. You can do it roughly like that:
Template:
<div #menuTrigger [matMenuTriggerFor]="menu" class="menu-trigger">I will be hidden</div>
<mat-menu #menu class="your-menu-class">
...
</mat-menu>
CSS:
.menu-trigger {
display: none;
}
Component:
class YourComponent {
@ViewChild(MatMenuTrigger) menuTrigger: MatMenuTrigger | undefined;
constructor(private readonly viewRef: ViewContainerRef) { }
someMethod() {
this.menuTrigger?.menuOpened.pipe(take(1)).subscribe(() => {
const menu = document.getElementsByClassName('your-menu-class')[0] as HTMLElement;
const position: DOMRect = this.viewRef.element.nativeElement.getBoundingClientRect();
menu.style.position = 'absolute';
menu.style.top = `${position.top}px`;
menu.style.left = `${position.width}px`;
});
this.menuTrigger?.openMenu();
}
}
You can also control the <mat-menu>
directly in the code.
Here is an example:
import { Component, ViewChild } from '@angular/core';
import { MatMenuTrigger } from '@angular/material/menu';
...
export class LanguageComponent {
@ViewChild('languageMenuTrigger') languageMenuTrigger: MatMenuTrigger;
...
openMenu() {
this.languageMenuTrigger.openMenu();
}
closeMenu() {
this.languageMenuTrigger.closeMenu();
}
}
<button
mat-button
[matMenuTriggerFor]="languageMenu"
#languageMenuTrigger="matMenuTrigger">
Language
<mat-icon>expand_more</mat-icon>
</button>
<mat-menu #languageMenu="matMenu">
<button
mat-menu-item>
English
</button>
<button
mat-menu-item>
Français
</button>
</mat-menu>
You need to get hold of MatMenuTrigger
instance from [matMenuTriggerFor]
element
#menuTrigger="matMenuTrigger" [matMenuTriggerFor]="menu"
where
#menuTrigger
is the template reference variablematMenuTrigger
isexportAs
property ofMatMenuTrigger
metadata
and then simply call
(click)="menuTrigger.openMenu()"
Stackblitz example
Read more about template reference variable here
- What is #auto attribute here and why it is required