2

I am using the standard Angular2 Material Menu structure to create a top bar menu items that open sub-menus, like the code below from my project:

<button mat-button matTooltip="Events..." matTooltipPosition="below" [mat-menu-trigger-for]="eventsMenu">
    <span hide-xs hide-gt-xs show-gt-sm>EVENTS</span>
    <mat-icon>event</mat-icon>
</button>

<mat-menu xPosition="after" yPosition="below" #eventsMenu="matMenu" [overlapTrigger]="false">
    <button mat-menu-item>
        <mat-icon>menu</mat-icon>
        <span>Agenda</span>
    </button>
    <button mat-menu-item>
        <mat-icon>menu</mat-icon>
        <span>Find Events</span>
    </button>
    ...

What bothers me about these sub-menus is that:

  • They don't open on mouse hover;
  • They don't close when I click in other main-menu item (I have to click outside the sub-menu container, it hides, then I can click the other menu item);
  • The main menu clicked item gets focused background even after the sub-menu hides (I think it's because I used the <button> tag).

I am new to Angular, just my second project using Angular Material. Can anyone tell me how can I sold these situations?

Forgot to mention: I am using Teradata Covalent template, if that changes anything...

NaN
  • 8,596
  • 20
  • 79
  • 153
  • The first question is not the Material Design scenario. see [this issue](https://github.com/angular/material2/issues/2080), you need to implement this feature by yourself using the overlay. – Xin Meng Mar 14 '18 at 14:25
  • I just make a demo of your code, I cannot see the 2nd and 3rd issues. https://angular-material-with-angular-v5-xin.stackblitz.io Could you make more description of your issue? – Xin Meng Mar 14 '18 at 14:28
  • [Docs site](https://material.angular.io/components/menu/overview#nested-menu) don't seem to have your issue: – p4r1 Mar 14 '18 at 15:01
  • @user1684458 it's true but, they only show one main menu, then how can we be sure if it's going to go the same way if there were more main-menu items? – NaN Mar 14 '18 at 15:21
  • @XinMeng hi darling, the 2nd issue happens in your stackblitz example too. We click in "Menu", it opens. The we click in "Event", but then "Menu" closes. You have to click again in "Event" for it to open, as if there was an invisible container over the screen avoiding us to click in other controls while a menu is opened. – NaN Mar 14 '18 at 15:25
  • Is there an option in which we could create an **horizontal menu list** instead of using **buttons** to simulate main menus? – NaN Mar 14 '18 at 15:35
  • @PSyLoCKe According to the official demo site, the behaviour is same. (try it on Menu api demo with the Theme picker menu button) I think it is right behaviour for the menu button. – Xin Meng Mar 14 '18 at 17:47

1 Answers1

3

To open the menu on hover, use the MatMenuTrigger object:

<button mat-button [mat-menu-trigger-for]="eventsMenu" #menuTrigger="matMenuTrigger" (mouseover)="menuTrigger.openMenu()">

The menu button receives focus when you click it. When the menu closes, focus returns to the last component which is the menu button. This is normal. You might be able to work around that by listening for the menu closing event and sending focus to something else.

The closing problem is difficult. There was one suggestion about that here.

You can add a div inside a mat-menu to layout menu items horizontally, but the problem with that is the sub-menus open to the right of the buttons not below, so you will need to adjust xPosition and yPosition. Also, you will need to find a way to open the top level menu since they are closed by default. One approach is below (there is probably a better way).

HTML

<!-- hidden button for opening the menu -->
<button mat-button [matMenuTriggerFor]="mainMenu" #mainMenuTrigger="matMenuTrigger" class="cdk-visually-hidden">
</button>

<!-- horizontal main menu -->
<mat-menu #mainMenu="matMenu">
  <div style="display: flex; justify-content: flex-start;">
    <button mat-button [matMenuTriggerFor]="file">File</button>
    <button mat-button [matMenuTriggerFor]="edit">Edit</button>
  </div>
</mat-menu>

<!-- submenus below -->

TS

import {Component, ViewChild} from '@angular/core';
import {MatMenuTrigger} from '@angular/material';
/**
 * @title Horizontal menu
 */
@Component({
  selector: 'horizontal-menu-example',
  templateUrl: 'horizontal-menu-example.html'
})
export class HorizontalMenuExample {
  @ViewChild('mainMenuTrigger') trigger: MatMenuTrigger;
  ngAfterViewInit() {
    setTimeout(() => {
      this.trigger.openMenu(); // open the main menu
    }, 0);
  }
}
G. Tranter
  • 16,766
  • 1
  • 48
  • 68