Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to show the angular material drop down on mouse over?

Now on clicking of the hamburger menu i am getting drop down list instead i need it on mouse hover on hamburger menu here is the stack blitz link.

enter image description here

like image 481
PGH Avatar asked Jan 22 '19 04:01

PGH


3 Answers

You can do this using matMenuTrigger Directive

<button mat-icon-button [matMenuTriggerFor]="menu" 
    #menuTrigger="matMenuTrigger" (mouseenter)="menuTrigger.openMenu()">

To hide menu, add mouseleave event for a menu.

Bundle all your menu items within a span or div tag. And then attach (mouseleave) event to it

<mat-menu #menu="matMenu" [overlapTrigger]="false">
    <span (mouseleave)="menuTrigger.closeMenu()">
      <button mat-menu-item>
        <mat-icon>home</mat-icon>
        <span>Home</span>
        ........
       <mat-icon>exit_to_app</mat-icon>
       <span>Logout</span>
     </button>
    </span>
</mat-menu>

Forked DEMO

like image 85
Amit Chigadani Avatar answered Oct 20 '22 07:10

Amit Chigadani


I know I am very late to the party, but none of the above really did the trick for me. I ended up writing a directive so solve this issue for me.

HoverDropDownDirective

import { NgModule } from '@angular/core';
import { Directive, Input, ElementRef, OnInit } from '@angular/core';
import { MatMenuTrigger, _MatMenu } from '@angular/material';

@Directive({
    selector: '[hoverDropDown]'
})
export class HoverDropDownDirective implements OnInit {
    isInHoverBlock = false;

    constructor(private el: ElementRef) {}

    @Input() hoverTrigger: MatMenuTrigger;
    @Input() menu: any;

    ngOnInit() {
        this.el.nativeElement.addEventListener('mouseenter', () => {
            this.setHoverState(true);
            this.hoverTrigger.openMenu();

            const openMenu = document.querySelector(`.mat-menu-after.${this.menu._elementRef.nativeElement.className}`);
            if (!openMenu) {
                this.hoverTrigger.closeMenu();
                return;
            }
            openMenu.addEventListener('mouseenter', () => {
                this.setHoverState(true);
            });
            openMenu.addEventListener('mouseleave', () => {
                this.setHoverState(false);
            });
        });
        this.el.nativeElement.addEventListener('mouseleave', () => {
            this.setHoverState(false);
        });
    }

    private setHoverState(isInBlock: boolean) {
        this.isInHoverBlock = isInBlock;
        if (!isInBlock) {
            this.checkHover();
        }
    }

    private checkHover() {
        setTimeout(() => {
            if (!this.isInHoverBlock && this.hoverTrigger.menuOpen) {
                this.hoverTrigger.closeMenu();
            }
        }, 50);
    }
}

@NgModule({
    declarations: [
        HoverDropDownDirective
    ],
    exports: [
        HoverDropDownDirective
    ]
})
export class HoverDropDownDirectiveModule {}

app.module

import { HoverDropDownDirectiveModule } from '../../directives/hover-drop-down.directive';

imports: [
    HoverDropDownDirectiveModule
]

HTML

<div *ngFor="let category of categories">
    <button #menuTrigger="matMenuTrigger"
            mat-button
            [matMenuTriggerFor]="children"
            (click)="navigateMain(category.Category)"

            hoverDropDown
            [menu]="children"
            [hoverTrigger]="menuTrigger">
             {{category.Category.Description}}
    </button>
    <mat-menu #children="matMenu" hasBackdrop="false">
        <button mat-menu-item *ngFor="let sub of category.SubCategories" (click)="navigateSubCategory(sub)">{{sub.Description}}</button>
    </mat-menu>
</div>

2 things to note:

  1. The 3 attributes in the Main Button ("hoverDropDown", "[menu]" and "[hoverTrigger]")
  2. hasBackdrop="false" attribute in the mat-menu

The hasBackdrop="false" attribute is documented on Angular Material. Hope this works for you...

like image 33
Ruan Avatar answered Oct 20 '22 07:10

Ruan


Add a reference variable for the mat button, use to fire click on a mouseover event.

<button mat-icon-button
        #matBtn
        (mouseover)="matBtn._elementRef.nativeElement.click()"
        [matMenuTriggerFor]="menu"
>

Note: I really don't prefer accessing "private" properties of an object like this, this solution of mine is more of a workaround, please use this if you don't find any other.

like image 1
Ashish Ranjan Avatar answered Oct 20 '22 09:10

Ashish Ranjan