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

我正在创建一个日期时间选择器控件的角度材料和有下面的代码来做到这一点

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

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

但是我想知道有没有可能在垫式日历上做到这一点

enter image description here

正如你可以看到在上面的图像目前当我选择一个日期,它是关闭菜单。有可能阻止吗?

65793 次浏览

只需将 (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 .

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

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>

在 TS:

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

您可以直接在组件中使用此指令。

以超文本标示语言(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>

保存为 filter.directive.ts 从“@angle/core”导入{ Directive,HostListener,HostBinding } ;

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


return false;
}
}

不幸的是,以上的答案对我都不起作用。如果你需要的菜单面板比内容更宽,没有地方你可以把 "$event.stopPropagation();",所以如果你点击垫菜单面板它将关闭。 幸运的是,仍然有办法避免这一点,通过“覆盖”click事件的 MatMenu。 这里有一个 stackblitz 的例子,感谢我的同事: < a href = “ https://stackblitz.com/edit/mat-menu-ability-close”rel = “ nofollow norefrer”> 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(),
);
}

这样,它将关闭,只有当你点击外面(这是一个很容易删除) ,如果你使用触发器。 这就是我想在我的项目的行为,我希望它将有用的人。

如果你想停止关闭垫菜单,甚至点击垫菜单-内容,我做了黑客作为补充 $event.stopPropogation()锚标签,而不是垫菜单。 因此,菜单日志将不会关闭,即使单击窗体上的任何地方。

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

你有很多选择,我邀请你尝试以下方法

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

如果你想防止关闭垫子菜单时点击框外的任何地方,否则删除它的 [ hasBackdrop ] = “ false”

尝试这种方法,在 div 中包装所有的 mat 菜单项,并停止传播任何单击事件。

<mat-menu #menu="matMenu" [hasBackdrop]="false">
<div (click)="$event.stopPropagation()" (keydown)="$event.stopPropagation()">
<button mat-menu-item>
<mat-icon>dialpad</mat-icon>
<span>Origin</span>
</button>
<button mat-menu-item disabled>
<mat-icon>voicemail</mat-icon>
<span>Check voice mail</span>
</button>
<button mat-menu-item>
<mat-icon>notifications_off</mat-icon>
<span>Disable alerts</span>
</button>
</div>
</mat-menu>