You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.29 14:01:09