Angular Material 15表格行失焦触发事件的替代实现方案
替代方案解决Angular Material v15表格行失去焦点触发方法的问题
因为<mat-row>本身不支持blur事件,你可以用以下几种可行方案实现需求:
方案1:给行添加tabindex并使用focusout事件
给<mat-row>设置tabindex让它能获取焦点,然后绑定focusout事件,当行失去焦点时触发方法。同时处理点击其他行时的焦点切换:
修改你的表格行代码:
<mat-row *matRowDef="let row; columns: displayedColumns;" tabindex="0" (focusout)="saveData(row)" (click)="$event.target.focus()" ></mat-row>
tabindex="0"让行可以通过点击或键盘聚焦(focusout)在元素失去焦点时触发,覆盖点击其他行或表格外区域的场景(click)事件确保点击行时主动获取焦点,保证focusout能正确触发
方案2:监听全局点击事件判断行失去焦点
通过监听document的点击事件,对比点击目标是否属于当前选中的行,触发保存逻辑:
- 在组件类中定义变量记录当前选中的行:
currentActiveRow: any;
- 给
<mat-row>绑定点击事件记录选中行:
<mat-row *matRowDef="let row; columns: displayedColumns;" (click)="setActiveRow(row)" ></mat-row>
- 在组件中实现逻辑:
setActiveRow(row: any) { // 如果之前有选中的行,先执行保存 if (this.currentActiveRow && this.currentActiveRow !== row) { this.saveData(this.currentActiveRow); } this.currentActiveRow = row; } @HostListener('document:click', ['$event']) onDocumentClick(event: MouseEvent) { const target = event.target as HTMLElement; // 判断点击的元素是否属于表格行 const isRowClicked = target.closest('mat-row') !== null; if (!isRowClicked && this.currentActiveRow) { this.saveData(this.currentActiveRow); this.currentActiveRow = null; } }
这个方案不需要行可聚焦,通过全局点击判断是否离开行区域。
方案3:使用Angular CDK的FocusMonitor服务
利用Angular CDK提供的FocusMonitor监听行的焦点变化,适合复杂的焦点管理场景:
- 导入依赖:
import { FocusMonitor } from '@angular/cdk/a11y'; import { ElementRef } from '@angular/core';
- 在组件中注入服务并监听行元素:
constructor(private focusMonitor: FocusMonitor) {} ngAfterViewInit() { // 获取所有mat-row元素 const rows = document.querySelectorAll('mat-row'); rows.forEach(row => { const rowElement = row as HTMLElement; // 设置tabindex让元素可聚焦 rowElement.tabIndex = 0; // 监听焦点变化 this.focusMonitor.monitor(rowElement).subscribe(focusOrigin => { if (!focusOrigin) { // 失去焦点时触发,focusOrigin为null表示失去焦点 const rowData = JSON.parse(rowElement.dataset['rowData'] || '{}'); this.saveData(rowData); } }); }); } ngOnDestroy() { // 销毁监听,防止内存泄漏 this.focusMonitor.stopMonitoringAll(); }
- 修改模板绑定行数据到dataset:
<mat-row *matRowDef="let row; columns: displayedColumns;" [attr.data-row-data]="row | json" ></mat-row>
这个方案更灵活,能处理键盘导航等各种焦点丢失场景。
内容的提问来源于stack exchange,提问作者Darrell
相关产品推荐
相关产品推荐

