Reputation: 61
I did a bunch of searching in an effort to find a clean way to hover a material menu to reveal its menu options, but unfortunately the solutions I found seemed to be a bit overly complex, or just straight up didn't work. So instead, I created my own solution using parts of what I found, and added in some logic of my own. You can find the answer below!
Upvotes: 2
Views: 2778
Reputation: 61
Here's the stackblitz: https://stackblitz.com/edit/angular-d56h4m
As for the explanation, I simply added some extra logic on the (mouseenter) and (mouseleave) listeners that just checks if the mouse has actually left the main menu button or the menu items yet with a very small delay. This is just a simple version, but I'm sure you can extend it as needed.
app.component.html:
<button
mat-button [matMenuTriggerFor]="menu"
#menuTrigger="matMenuTrigger"
(mouseenter)="openResourceMenu(); recheckIfInMenu = true"
(mouseleave)="closeResourceMenu(); recheckIfInMenu = false"> Resources
</button>
<mat-menu #menu="matMenu" [overlapTrigger]="false">
<span
(mouseenter)="recheckIfInMenu = true"
(mouseleave)="closeResourceMenu(); recheckIfInMenu = false">
<button mat-menu-item>
Buyers
</button>
<button mat-menu-item>
Sellers
</button>
</span>
</mat-menu>
app.component.ts:
import { Component, OnInit, ViewChild } from '@angular/core';
import {MatMenuTrigger} from '@angular/material';
@Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: [ './app.component.css' ]
})
export class AppComponent implements OnInit {
@ViewChild(MatMenuTrigger, {static: false}) trigger: MatMenuTrigger;
recheckIfInMenu: boolean;
ngOnInit() {
this.recheckIfInMenu = false;
}
openResourceMenu() {
this.trigger.openMenu();
}
closeResourceMenu() {
setTimeout(() => {
if (this.recheckIfInMenu === false) {
this.trigger.closeMenu();
}
}, 175);
}
}
styles.css:
.cdk-overlay-container{
top:67px;
}
.cdk-overlay-connected-position-bounding-box{
top:0 !important;
}
Don't forget to import the menu module too!
import { MatMenuModule } from '@angular/material/menu';
The biggest thing that helped make it work for me was delaying the check of whether or not the mouse is still in the menu, I have it set to 175 ms. By doing this, the menu will stay up for a split second allowing the user to make it into the menu items before the menu itself dismisses. It also will check when leaving from the menu button itself and properly close the menu, which other solutions lacked accounting for.
Other links that got me on this path:
How to open and close Angular mat menu on hover
How to make Material Design Menu (mat-menu) hide on mouseleave
So far the only issue I've come across is that sometimes there's a slight stutter when moving the mouse over the dropdown item fast, but to me this is worth the tradeoff.
Upvotes: 4