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

Angular使用ng-template实现Material递归mat-menu渲染异常求助

问题根因

你代码的核心问题出在子菜单存在性判断逻辑错误,其次可补充触发配置优化交互:

  1. 你给所有MenuItem都默认定义了children: []空数组,而JS中空数组属于真值,所以原判断*ngIf="parentItem.children"永远成立,所有菜单项都会走带子菜单的menuItem模板,哪怕实际没有子项,导致空的mat-menu绑定引发渲染异常。
  2. 未显式配置子菜单悬浮触发逻辑,部分版本Angular Material默认仅支持点击触发嵌套菜单。
修复方案

步骤1:修正子菜单判断条件

把所有子项存在性判断改为校验children数组长度,空数组会被判定为无有效子项,走普通菜单项逻辑。

步骤2:(可选)添加悬浮触发配置

给子菜单触发按钮添加matMenuTriggerHoverDelay配置,实现hover自动弹出子菜单,符合常规菜单交互习惯。

步骤3:(可选)配置子菜单不覆盖父菜单

给mat-menu添加[overlapTrigger]="false"属性,避免子菜单弹出时遮挡父菜单、触发父菜单关闭。

修改后的完整模板代码
<button mat-button [matMenuTriggerFor]="itemMenu">
  {{ startMenuItem.description }}
</button>
<mat-menu #itemMenu="matMenu" [overlapTrigger]="false">
  <ng-container *ngFor="let childItem of startMenuItem.children">
    <ng-container
      *ngTemplateOutlet="recursiveMenuTmpl; context: { $implicit: childItem }"
    >
    </ng-container>
  </ng-container>
</mat-menu>

<ng-template #recursiveMenuTmpl let-parentItem>
  <!-- 修正判断逻辑:只有children长度大于0才识别为有子菜单 -->
  <ng-container *ngIf="parentItem.children?.length > 0">
    <ng-container
      *ngTemplateOutlet="menuItem; context: { $implicit: parentItem }"
    ></ng-container>
  </ng-container>
  <ng-container *ngIf="!parentItem.children?.length">
    <ng-container
      *ngTemplateOutlet="singleItem; context: { $implicit: parentItem }"
    ></ng-container>
  </ng-container>
</ng-template>

<ng-template #menuItem let-rootItem>
  <!-- 添加悬浮触发延迟,单位ms,可自行调整数值 -->
  <button [matMenuTriggerFor]="itemMenu" mat-menu-item [matMenuTriggerHoverDelay]="150">
    {{ rootItem.description }}
  </button>
  <mat-menu #itemMenu="matMenu" [overlapTrigger]="false">
    <ng-container *ngFor="let childItem of rootItem.children">
      <ng-container
        *ngTemplateOutlet="recursiveMenuTmpl; context: { $implicit: childItem }"
      >
      </ng-container>
    </ng-container>
  </mat-menu>
</ng-template>

<ng-template #singleItem let-item>
  <button *ngIf="item.route" mat-menu-item [routerLink]="item.uri">
    {{ item.description }}
  </button>
  <button *ngIf="!item.route" mat-menu-item (click)="onOpenUrl(item.uri)">
    {{ item.description }}
  </button>
</ng-template>
补充注意事项

请确保你已经在对应模块中导入了以下依赖:

  • MatMenuModule
  • MatButtonModule
  • RouterModule(如果使用路由跳转功能)

修改后原本缺失的子菜单展开箭头会自动渲染,hover即可弹出子菜单且父菜单不会自动关闭。

内容的提问来源于stack exchange,提问作者Jeroen

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.07 02:27:03