简体   繁体   English

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

[英]How to prevent angular material mat-menu from closing?

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 做到这一点

在此处输入图片说明

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?有可能阻止吗?

You just add (click) = "$event.stopPropagation()" to the parent element of these calendars.您只需将(click) = "$event.stopPropagation()"到这些日历的父元素即可。 Like below,像下面,

<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 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
}

if You want to stop closing mat-menu even on clicking on mat-menu-content i did hack as added $event.stopPropogation() on a anchor tag instead of mat-menu.如果您想停止关闭 mat-menu,即使单击 mat-menu-content 我确实在锚标签上添加了$event.stopPropogation()而不是 mat-menu。 so Menu dailog will not close even if clicked anywhere on the form.因此,即使单击表单上的任何位置,菜单 dailog 也不会关闭。

Example:- 
    <mat-menu #nameAndDescriptioContextMenu="matMenu" [hasBackdrop]="false">
         <a (click)="$event.stopPropagation();$event.preventDefault();">
               <div>
                 Form Group Form
               </div> 
         </a> 
    </mat-menu>

You have many options, I invite you try the following你有很多选择,我邀请你尝试以下

    <mat-menu [hasBackdrop]="false">
     <div  (click)="$event.stopPropagation()" (keydown)="$event.stopPropagation()">
     ...
     </div>
    </mat-menu>

the [hasBackdrop]="false" if you want to prevent closing mat-menu when clicking anywhere outside the box, otherwise remove it [hasBackdrop]="false"如果你想在点击框外的任何地方时阻止关闭 mat-menu,否则将其删除

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();"如果您需要菜单面板比内容宽得多,则没有地方可以放置"$event.stopPropagation();" on, so if you click on mat-menu-panel it will close.上,因此如果您单击 mat-menu-panel,它将关闭。 Luckily, there is still a way to avoid this, by 'overriding' click event of MatMenu.幸运的是,仍然有一种方法可以避免这种情况,通过“覆盖” MatMenu 的click事件。 Here is stackblitz example, thanks to my colleague: https://stackblitz.com/edit/mat-menu-disable-close这是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.这就是我在我的项目中想要的行为,我希望它对某人有用。

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;
  }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM