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

Angular:关闭mat-menu并设置焦点到上一个/下一个元素的实现方法

实现MatMenu中链接的Tab导航焦点控制

问题代码

模板代码

<ng-container>
  <ng-container>
    <div class="class1" tabindex="0" [matMenuTriggerFor]="menu" #menuTrigger="matMenuTrigger">
      <div class="customclass">
        <i class="fa fa-bell-o"></i>
        <h2>Main Menu</h2>
      </div>
    </div>
  </ng-container>

<mat-menu #menu="matMenu" class="myClass" >
    <div class="Custom">      
        <div mat-menu-item (click)="$event.stopPropagation()" (keydown)="myFunc($event)">
         <div class="class2">
      <h3>Label</h3>     
        <div class="class3">
        <p> some text, <a href="link address">first link</a>.
            Some Test text and link <a href="address" >second link</a>
        </p>
      </div>
        </div>      
    </div>
  </mat-menu>

TS代码

let myLinks = this.elRef.nativeElement.getElementsByTagName('a');
   
for (let i = 0; i <= anchors.length-1; i++) {
  myLinks[i].setAttribute('tabindex', '0');
}

myFunc(event: { stopPropagation: () => void }) {
  event.stopPropagation();
}

需求

  • 在第一个链接按下Shift+Tab时关闭菜单,同时将焦点设置到Main Menu;
  • 在最后一个链接按下Tab时关闭菜单,同时将焦点设置到下一个元素。

实现步骤

1. 修正TS变量错误

原代码循环中误用了未定义的anchors变量,替换为myLinks:

const myLinks = this.elRef.nativeElement.getElementsByTagName('a');
for (let i = 0; i < myLinks.length; i++) {
  myLinks[i].setAttribute('tabindex', '0');
}

2. 获取菜单触发器实例

在组件类中通过@ViewChild拿到menuTrigger的引用,用于控制菜单开关:

import { Component, ViewChild, ElementRef } from '@angular/core';
import { MatMenuTrigger } from '@angular/material/menu';

@Component({
  // 你的组件元数据(选择器、模板、样式等)
})
export class YourComponent {
  @ViewChild('menuTrigger') private menuTrigger!: MatMenuTrigger;

  constructor(private elRef: ElementRef) {}

  // 其他组件逻辑...
}

3. 完善键盘事件处理函数

修改myFunc,判断当前焦点链接的位置,处理Shift+Tab和Tab的场景:

myFunc(event: KeyboardEvent) {
  event.stopPropagation();
  const myLinks = this.elRef.nativeElement.getElementsByTagName('a');
  const currentLink = event.target as HTMLAnchorElement;

  // 第一个链接按Shift+Tab:关闭菜单,聚焦到Main Menu
  if (event.shiftKey && event.key === 'Tab' && currentLink === myLinks[0]) {
    this.menuTrigger.closeMenu();
    const mainMenu = this.elRef.nativeElement.querySelector('.class1');
    mainMenu?.focus();
    event.preventDefault();
  }

  // 最后一个链接按Tab:关闭菜单,聚焦到下一个可交互元素
  if (!event.shiftKey && event.key === 'Tab' && currentLink === myLinks[myLinks.length - 1]) {
    this.menuTrigger.closeMenu();
    event.preventDefault();
    // 延迟确保菜单关闭后再切换焦点
    setTimeout(() => {
      const focusableElements = Array.from(
        document.querySelectorAll('button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])')
      );
      const currentIndex = focusableElements.indexOf(currentLink);
      if (currentIndex < focusableElements.length - 1) {
        focusableElements[currentIndex + 1]?.focus();
      }
    }, 100);
  }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 17:02:02