Javascript 如何防止角材料垫菜单关闭?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/46967970/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 03:41:56  来源:igfitidea点击:

How to prevent angular material mat-menu from closing?

javascriptangularangular-material2

提问by Umamaheswaran

I'm creating a date time picker control in the angular material and having the below code to do that

我正在角度材料中创建一个日期时间选择器控件并使用以下代码来执行此操作

<button mat-button [matMenuTriggerFor]="menu">
    <mat-icon>date_range</mat-icon>
    <span>Date Range</span>
</button>
<mat-menu #menu="matMenu">
    <div fxLayout="row">
        <div fxLayout="column">
            <button (click)="setInterval(15)" mat-menu-item>Last 15 minutes</button>
            <button (click)="setInterval(360)" mat-menu-item>Last 6 hours</button>
            <button (click)="setInterval(1440)" mat-menu-item>Last 24 hours</button>
            <button (click)="setInterval(2880)" mat-menu-item>Last 2 days</button>
            <button (click)="setInterval(10080)" mat-menu-item>Last 7 days</button>
            <button (click)="setInterval(-1)" [matMenuTriggerFor]="dateTimeMenu" mat-menu-item>Custom</button>
        </div>
        <mat-menu class="date-range-menu" #dateTimeMenu="matMenu">
            <div fxLayout="row">
                <div fxLayout="column">
                    <b>From</b>
                    <mat-calendar></mat-calendar>
                </div>
                <div fxLayout="column">
                    <b>To</b>
                    <mat-calendar></mat-calendar>
                </div>
            </div>
        </mat-menu>
    </div>
</mat-menu>

Currently when ever I click a button it is closing the menu. I know we can do $event.stoppropagation() on each mat-menu-item to prevent it from closing.

目前,当我点击一个按钮时,它正在关闭菜单。我知道我们可以在每个 mat-menu-item 上执行 $event.stoppropagation() 以防止它关闭。

But I want to know is it possible to do that for mat-calendar

但我想知道是否可以为 mat-calendar 做到这一点

enter image description here

在此处输入图片说明

As you can see in the above image currently when i select a date it is closing the menu. Is it possible to prevent that?

正如您在上图中所看到的,当我选择一个日期时,它正在关闭菜单。有可能阻止吗?

回答by Anik

You just add (click) = "$event.stopPropagation()"to the parent element of these calendars. Like below,

您只需添加(click) = "$event.stopPropagation()"到这些日历的父元素即可。像下面,

<mat-menu class="date-range-menu" #dateTimeMenu="matMenu">
    <div fxLayout="row">
        <div fxLayout="column" (click)="$event.stopPropagation();">
            <b>From</b>
            <mat-calendar></mat-calendar>
        </div>
        <div fxLayout="column" (click)="$event.stopPropagation();">
            <b>To</b>
            <mat-calendar></mat-calendar>
        </div>
    </div>
</mat-menu>

Stackblitz demo.

Stackblitz 演示

回答by JLazar0

By giving a return to the previous solution, encapsulating the instruction in a method allows not to close the menu and continue executing instructions

通过返回之前的解决方案,将指令封装在方法中允许不关闭菜单并继续执行指令

IN HTML:

在 HTML 中:

<mat-menu class="date-range-menu" #dateTimeMenu="matMenu">
    <div fxLayout="row">
        <div fxLayout="column" (click)="doSomething($event);">
            <b>From</b>
            <mat-calendar></mat-calendar>
        </div>
        <div fxLayout="column" (click)="doSomething($event)">
            <b>To</b>
            <mat-calendar></mat-calendar>
        </div>
    </div>
</mat-menu>

IN TS:

在 TS:

doSomething($event:any){
    $event.stopPropagation();
    //Another instructions
}

回答by gaurav sharma

you can use this directive directly in your component.

你可以直接在你的组件中使用这个指令。

in HTML

在 HTML 中

<mat-menu class="date-range-menu" #dateTimeMenu="matMenu">
    <div fxLayout="row">
        <div fxLayout="column" mat-filter-item>
            <b>From</b>
            <mat-calendar></mat-calendar>
        </div>
        <div fxLayout="column" mat-filter-item >
            <b>To</b>
            <mat-calendar></mat-calendar>
        </div>
    </div>
</mat-menu>

save it as filter.directive.ts import { Directive, HostListener, HostBinding } from "@angular/core";

将其另存为 filter.directive.ts import { Directive, HostListener, HostBinding } from "@angular/core";

@Directive({
  selector: "[mat-filter-item]"
})
export class FilterItemDirective {
  @HostListener("click", ["$event"])
  onClick(e: MouseEvent) {
    e.stopPropagation();
    e.preventDefault();

    return false;
  }
}

回答by Amarula

Unfortunately, none of the above answers worked for me. In cases when you need menu panel to be much wider than the content, there is no place you can put "$event.stopPropagation();"on, so if you click on mat-menu-panel it will close. Luckily, there is still a way to avoid this, by 'overriding' clickevent of MatMenu. Here is stackblitz example, thanks to my colleague: https://stackblitz.com/edit/mat-menu-disable-close

不幸的是,上述答案都不适合我。如果您需要菜单面板比内容宽得多,则没有地方可以放置"$event.stopPropagation();",因此如果您单击 mat-menu-panel 它将关闭。幸运的是,仍然有一种方法可以通过“覆盖” clickMatMenu 事件来避免这种情况。这是stackblitz的例子,感谢我的同事:https://stackblitz.com/edit/mat-menu-disable-close

ngAfterViewInit() {
    // Inject our custom logic of menu close
    (this.searchMenu as any).closed = this.searchMenu.close = this.configureMenuClose(this.searchMenu.close);
  }

private configureMenuClose(old: MatMenu['close']): MatMenu['close'] {
    const upd = new EventEmitter();
    feed(upd.pipe(
      filter(event => {
        if (event === 'click') {
          // Ignore clicks inside the menu 
          return false;
        }
        return true;
      }),
    ), old);
    return upd;
  }
}
function feed<T>(from: Observable<T>, to: Subject<T>): Subscription {
  return from.subscribe(
    data => to.next(data),
    err => to.error(err),
    () => to.complete(),
  );
}

This way, it will close only if you click outside (that's an easy to remove) and if you use trigger. That is the behavior I wanted in my project and I hope it will be useful for someone.

这样,只有当您单击外部(这很容易删除)并且您使用触发器时,它才会关闭。这就是我在我的项目中想要的行为,我希望它对某人有用。