Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Open Angular Material Menu Programmatically using ViewChild on MatMenuTrigger

How can an Angular Material menu be opened programmatically using Template Reference Variable on button trigger, which is accessed in component using ViewChild?

The menu opens normally on click, but I'd like to open it programmatically on mouseover.

(mouseover) event handler gives error: Cannot read property 'openMenu' of undefined.

So why is clickHoverMenuTrigger undefined in the component?

Here's the component html

<button mat-icon-button [matMenuTriggerFor]="clickHoverMenu" 
  #clickHoverMenuTrigger (mouseover)="openOnMouseOver()">
  <mat-icon>notifications</mat-icon>
</button>

Here's the component typescript

@ViewChild(MatMenuTrigger) clickHoverMenuTrigger: MatMenuTrigger;

openOnMouseOver() {
  this.clickHoverMenuTrigger.openMenu();
}

This method is documented here https://material.angular.io/components/menu/overview

Same problem raised and answered here How do I access mat menu trigger from typescript (I don't have the reputation to comment on that)

It looks like I'm doing exactly what is stated in the documentation and the StackOverflow solution above.

As clickHoverMenuTrigger is undefined, it must be an issue with @ViewChild.

Code on Stackblitz. Open console to see error.

like image 756
Alex Cooper Avatar asked Dec 15 '18 12:12

Alex Cooper


People also ask

What is matMenuTriggerFor?

matMenuTriggerFor is passed the menu identifier to attach the menus.

How to change the position of mat menu?

Changing mat menu positionThe xPosition attribute sets the menu all along the horizontal axis. The yPosition attribute is used to change the menu's vertical position. Set the yPosition property to "above" to display the menu just above the menu trigger element. The values "above" and "below" are accepted by yPosition.

What is mat menu panel?

<mat-menu> is a floating panel containing list of options. Basic menu. link code open_in_new. Menu. By itself, the <mat-menu> element does not render anything.


1 Answers

Just change the @ViewChild to

@ViewChild('clickHoverMenuTrigger') clickHoverMenuTrigger: MatMenuTrigger;

Overall code should be:

<h1>2 buttons, 2 Menus</h1>

<ol>
  <li>Standard Material Button opens menu on click </li>
  <li>Same, but with event handler to open menu on mouseover</li>
</ol>

<button mat-icon-button [matMenuTriggerFor]="clickMenu"
  #clickMenuTrigger="matMenuTrigger">
  <mat-icon>touch_app</mat-icon>
</button>

<button mat-icon-button [matMenuTriggerFor]="clickHoverMenu" 
  #clickHoverMenuTrigger="matMenuTrigger" (mouseover)="openOnMouseOver()">
  <mat-icon>notifications</mat-icon>
</button>

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

<mat-menu #clickHoverMenu="matMenu">
  <button mat-menu-item>New items</button>
</mat-menu>

ts:

export class AppComponent {

  @ViewChild('clickHoverMenuTrigger') clickHoverMenuTrigger: MatMenuTrigger;

  openOnMouseOver() {
    this.clickHoverMenuTrigger.openMenu();
  }
}

DEMO

like image 52
Fateme Fazli Avatar answered Oct 02 '22 01:10

Fateme Fazli