如何通过双击Tab键关闭Mat Calendar?Tab事件失效问题求助
解决Mat Calendar Tab键无法关闭及事件失效问题
问题描述
按下Tab键会打开Mat Calendar,但再次按Tab键时无法关闭它。日历打开后Tab方法或事件便会失效,除非按下Esc键。
截图

当前代码
HTML代码
<div fxLayout="row" style="max-width: 100px;"> <input [readonly]="true" (click)="openPicker(pickerTargetDate);" [(ngModel)]="data.targetDate" appFocusOnLoad (focus)="pickerTargetDate.open()" (keydown.Tab)="onEditTableInputsKeydownTab(i, 'actualProjectedDate')" matInput [matDatepicker]="pickerTargetDate" (dateChange)="dateChange(data,'parent','targetDate')" > <mat-datepicker #pickerTargetDate></mat-datepicker> <span *ngIf="data.targetDate && data.isRequired" (click)="openPicker(pickerTargetDate);" style="font-size: 20px;padding-top: 4px;margin-right:5px;"> calendar_today </span> </div>
TypeScript代码
onEditKeydownTab(index, columnName: string) { this.editTable(index, columnName) } editTable(index:number,columnName: string) { this.indexEditing=index; this.selectedCell = columnName; }
解决方案
核心思路
Mat Datepicker打开后会接管焦点管理,默认Tab行为会在日历内部元素间循环,无法触发输入框的Tab事件。我们需要手动拦截Tab事件,根据日历状态决定打开/关闭,并处理焦点转移。
修改后的代码实现
HTML部分
<div fxLayout="row" style="max-width: 100px;"> <input [readonly]="true" (click)="openPicker(pickerTargetDate)" [(ngModel)]="data.targetDate" appFocusOnLoad (focus)="pickerTargetDate.open()" (keydown.Tab)="handleTabInteraction($event, pickerTargetDate, i, 'actualProjectedDate')" matInput [matDatepicker]="pickerTargetDate" (dateChange)="dateChange(data,'parent','targetDate')" > <mat-datepicker #pickerTargetDate></mat-datepicker> <span *ngIf="data.targetDate && data.isRequired" (click)="openPicker(pickerTargetDate)" style="font-size: 20px;padding-top: 4px;margin-right:5px;"> calendar_today </span> </div>
TypeScript部分
handleTabInteraction(event: KeyboardEvent, picker: any, index: number, columnName: string) { // 阻止默认Tab行为,避免日历内部焦点循环 event.preventDefault(); if (picker.opened) { // 关闭日历 picker.close(); // 执行原有Tab逻辑,切换到目标单元格 this.editTable(index, columnName); // 可选:若需要将焦点直接移到下一个元素,可添加如下逻辑 // const nextElement = event.target?.nextElementSibling; // if (nextElement) (nextElement as HTMLElement).focus(); } else { // 打开日历 picker.open(); } } onEditKeydownTab(index: number, columnName: string) { this.editTable(index, columnName); } editTable(index: number, columnName: string) { this.indexEditing = index; this.selectedCell = columnName; }
关键说明
- 拦截默认行为:通过
event.preventDefault()阻止Tab键的默认焦点切换,避免日历内部的元素获取焦点。 - 状态判断:直接通过日历实例的
opened属性判断当前状态,执行打开或关闭操作。 - 焦点转移:关闭日历后调用原有
editTable逻辑,确保Tab键能正常切换到目标编辑单元格,也可根据需求手动指定下一个焦点元素。
内容的提问来源于stack exchange,提问作者Mark Latin
相关产品推荐
相关产品推荐

