Angular v12+Material v12:嵌套mat-menu的自定义组件被键盘焦点跳过
针对你遇到的MatMenu中嵌套自定义组件app-alert-update后,上下方向键导航跳过该组件的问题,可通过以下几种方案解决:
方案一:让自定义组件继承MatMenuItem类
MatMenu的键盘导航依赖FocusKeyManager,只会识别实现了FocusableOption接口的元素,而MatMenuItem本身已实现该接口。让自定义组件直接继承MatMenuItem,并在providers中配置自身作为MatMenuItem的实现,就能让导航系统正确识别它:
import { MatMenuItem } from '@angular/material/menu'; import { Component, Input } from '@angular/core'; @Component({ selector: 'app-alert-update', templateUrl: './alert-update.component.html', styleUrls: ['./alert-update.component.css'], providers: [{ provide: MatMenuItem, useExisting: AlertUpdateComponent }] }) export class AlertUpdateComponent extends MatMenuItem { // 自定义组件的输入属性或逻辑 @Input() alertMessage: string; }
方案二:手动将内部MatMenuItem注册到父菜单的items集合
如果不想继承组件,可在自定义组件中注入父级MatMenu,并将内部的mat-menu-item实例添加到菜单的items集合中,让导航系统感知到它:
- 组件模板中给内部
mat-menu-item添加模板引用:
<!-- alert-update.component.html --> <mat-menu-item #innerMenuItem> <!-- 自定义组件内容 --> {{ alertMessage }} </mat-menu-item>
- 组件类中注入MatMenu并添加内部菜单项:
import { Component, Input, ViewChild, OnInit } from '@angular/core'; import { MatMenu, MatMenuItem } from '@angular/material/menu'; @Component({ selector: 'app-alert-update', templateUrl: './alert-update.component.html', styleUrls: ['./alert-update.component.css'] }) export class AlertUpdateComponent implements OnInit { @Input() alertMessage: string; @ViewChild('innerMenuItem') innerMenuItem: MatMenuItem; constructor(private menu: MatMenu) {} ngOnInit(): void { if (this.innerMenuItem && this.menu) { this.menu.items.add(this.innerMenuItem); } } }
方案三:手动实现FocusableOption接口
若以上方案不适用,可让自定义组件实现FocusableOption接口,将焦点操作转发给内部的mat-menu-item:
import { Component, Input, ViewChild } from '@angular/core'; import { FocusableOption } from '@angular/cdk/a11y'; import { MatMenuItem } from '@angular/material/menu'; @Component({ selector: 'app-alert-update', templateUrl: './alert-update.component.html', styleUrls: ['./alert-update.component.css'], providers: [{ provide: MatMenuItem, useExisting: AlertUpdateComponent }] }) export class AlertUpdateComponent implements FocusableOption { @Input() alertMessage: string; @ViewChild('innerMenuItem') innerMenuItem: MatMenuItem; // 实现FocusableOption的focus方法,将焦点传递给内部菜单项 focus(): void { this.innerMenuItem.focus(); } }
额外注意事项
- 避免用无焦点能力的容器(如普通
div)包裹自定义组件的根元素,防止焦点被隔离; - 确保Angular Material 12版本中
MatMenu的items集合支持add操作(v12中该集合为Collection<MatMenuItem>,支持此操作)。
内容的提问来源于stack exchange,提问作者Natdrip
相关产品推荐
相关产品推荐

