Angular嵌套mat-menu勾选复选框时关闭的解决方法
问题描述
有一个嵌套的mat-menu,内部包含用于多选的复选框。点击复选框时菜单会自动关闭,需求是保持菜单打开以完成多项选择。
环境版本:
@angular/core: ^17.1.1@angular/material: ^17.2.0
当前代码:
<mat-menu #actionsMenu="matMenu" id="actions-menu"> <button [matMenuTriggerFor]="selectColMenu" id="select-columns" mat-menu-item> <mat-icon>arrow_left</mat-icon> <span class="small">Select Columns</span> </button> </mat-menu> <mat-menu #selectColMenu="matMenu"> @for(c of columnsCopy; track c; ) { <button class="form-check" (click)="$event.stopPropagation()" (keydown)="$event.stopPropagation()" mat-menu-item> <input class="form-check-input mx-1" type="checkbox" [value]="c" (click)="$event.stopPropagation()" [checked]="checkedColumns.has(c.key)" (change)="toggleColumns(c.key); $event.stopPropagation()" (keydown)="$event.stopPropagation()" /> <label class="form-check-label small" style="margin-top: 2px"> {{ c.title }} </label> </button> } </mat-menu>
解决方案
核心问题是mat-menu-item按钮的点击事件会触发Angular Material菜单的默认关闭逻辑,即使添加了stopPropagation也无法完全阻止。以下是几种可行的解决方法:
方法一:替换mat-menu-item为普通容器
将包含复选框的button替换成div,移除mat-menu-item指令,这样就不会触发菜单的关闭逻辑。同时添加基础样式模拟菜单选项的交互效果:
模板修改:
<mat-menu #selectColMenu="matMenu"> @for(c of columnsCopy; track c; ) { <div class="form-check d-flex align-items-center p-2" style="cursor: pointer; width: 100%"> <input class="form-check-input mx-1" type="checkbox" [value]="c" [checked]="checkedColumns.has(c.key)" (change)="toggleColumns(c.key)" /> <label class="form-check-label small mb-0 flex-grow-1"> {{ c.title }} </label> </div> } </mat-menu>
样式补充:
.mat-menu-content > div:hover { background-color: rgba(0, 0, 0, 0.04); }
这种方法实现简单,体验自然,是最推荐的方案。
方法二:通过closed事件阻止菜单关闭
监听子菜单的closed事件,判断是否为复选框点击导致的关闭,若是则阻止菜单关闭:
组件类代码:
import { MatMenu } from '@angular/material/menu'; import { ViewChild } from '@angular/core'; @Component({ // 组件元数据 }) export class YourComponent { @ViewChild('selectColMenu') selectColMenu!: MatMenu; private isCheckboxTriggered = false; markCheckboxClick() { this.isCheckboxTriggered = true; // 延迟重置状态,确保菜单关闭逻辑执行完成 setTimeout(() => this.isCheckboxTriggered = false, 100); } handleMenuClose(event: Event) { if (this.isCheckboxTriggered) { event.preventDefault(); event.stopPropagation(); } } }
模板修改:
<mat-menu #selectColMenu="matMenu" (closed)="handleMenuClose($event)"> @for(c of columnsCopy; track c; ) { <button class="form-check" mat-menu-item> <input class="form-check-input mx-1" type="checkbox" [value]="c" (click)="markCheckboxClick(); $event.stopPropagation()" [checked]="checkedColumns.has(c.key)" (change)="toggleColumns(c.key)" /> <label class="form-check-label small" style="margin-top: 2px"> {{ c.title }} </label> </button> } </mat-menu>
方法三:启用disableClose属性(不推荐)
给子菜单添加[disableClose]="true",这样点击菜单内部任何区域都不会关闭,但需要手动添加关闭按钮,用户体验较差:
<mat-menu #selectColMenu="matMenu" [disableClose]="true"> @for(c of columnsCopy; track c; ) { <button class="form-check" mat-menu-item> <!-- 复选框代码保持不变 --> </button> } <button mat-menu-item (click)="selectColMenu.close()">关闭</button> </mat-menu>
内容的提问来源于stack exchange,提问作者skdonthi
相关产品推荐
相关产品推荐

