Angular实现左右箭头键切换Material Table单元格焦点
实现Material Table输入框通过左右箭头切换焦点
核心思路
要实现焦点切换,关键是定位到相邻单元格的输入框元素并调用focus()方法。我们可以通过模板引用变量收集所有输入框,结合行索引和列索引计算目标输入框的位置,最终完成焦点跳转。
步骤1:修改HTML模板
给输入框添加模板引用变量#cellInput,同时传递当前行索引和列key到切换方法中(兼容多行场景):
<table mat-table [dataSource]="dataSource"> <ng-container [matColumnDef]="col.key" *ngFor="let col of columnsSchema"> <th mat-header-cell *matHeaderCellDef> {{ col?.label }} </th> <td mat-cell *matCellDef="let element; let rowIndex = index;"> <mat-form-field (keyup.arrowright)="moveRight(rowIndex, col.key)" (keyup.arrowleft)="moveLeft(rowIndex, col.key)"> <input #cellInput [type]="col?.type" matInput [(ngModel)]="element[col.key]" /> </mat-form-field> </td> </ng-container> <tr mat-header-row *matHeaderRowDef="displayedColumns"></tr> <tr mat-row *matRowDef="let row; columns: displayedColumns"></tr> </table>
步骤2:更新组件TS代码
- 导入所需依赖:
import { Component, OnInit, ViewChildren, QueryList, ElementRef } from '@angular/core'; import { VERSION } from '@angular/core'; import { MatTableDataSource } from '@angular/material/table';
- 添加ViewChildren收集所有输入框:
@ViewChildren('cellInput') cellInputs!: QueryList<ElementRef<HTMLInputElement>>;
- 修改
moveRight和moveLeft方法,实现焦点切换逻辑:
moveRight(rowIndex: number, colKey: string) { const colIndex = this.displayedColumns.findIndex(key => key === colKey); // 最后一列不处理 if (colIndex === this.displayedColumns.length - 1) return; const currentInputIdx = rowIndex * this.displayedColumns.length + colIndex; const targetInput = this.cellInputs.toArray()[currentInputIdx + 1]; targetInput?.nativeElement.focus(); } moveLeft(rowIndex: number, colKey: string) { const colIndex = this.displayedColumns.findIndex(key => key === colKey); // 第一列不处理 if (colIndex === 0) return; const currentInputIdx = rowIndex * this.displayedColumns.length + colIndex; const targetInput = this.cellInputs.toArray()[currentInputIdx - 1]; targetInput?.nativeElement.focus(); }
完整TS组件代码
import { Component, OnInit, ViewChildren, QueryList, ElementRef } from '@angular/core'; import { VERSION } from '@angular/core'; import { MatTableDataSource } from '@angular/material/table'; export interface SpecimenType { Test1: string; Test2: string; Test3: string; Test4: string; } const COLUMNS_SCHEMA = [ { key: 'Test1', type: 'number', label: 'Test1' }, { key: 'Test2', type: 'number', label: 'Test2' }, { key: 'Test3', type: 'number', label: 'Test3' }, { key: 'Test4', type: 'number', label: 'Test4' }, ]; @Component({ selector: 'my-app', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) export class AppComponent implements OnInit { name = 'Angular ' + VERSION.major; @ViewChildren('cellInput') cellInputs!: QueryList<ElementRef<HTMLInputElement>>; columnsSchema: any = COLUMNS_SCHEMA; selectedSpecimanType!: SpecimenType; displayedColumns: string[] = COLUMNS_SCHEMA.map(col => col.key); dataSource = new MatTableDataSource<any>(); ngOnInit(): void { this.dataSource.data = [{ Test1: 0, Test2: 0, Test3: 0, Test4: 0}]; } moveRight(rowIndex: number, colKey: string) { const colIndex = this.displayedColumns.findIndex(key => key === colKey); if (colIndex === this.displayedColumns.length - 1) return; const currentInputIdx = rowIndex * this.displayedColumns.length + colIndex; const targetInput = this.cellInputs.toArray()[currentInputIdx + 1]; targetInput?.nativeElement.focus(); } moveLeft(rowIndex: number, colKey: string) { const colIndex = this.displayedColumns.findIndex(key => key === colKey); if (colIndex === 0) return; const currentInputIdx = rowIndex * this.displayedColumns.length + colIndex; const targetInput = this.cellInputs.toArray()[currentInputIdx - 1]; targetInput?.nativeElement.focus(); } }
原理说明
- 通过
@ViewChildren('cellInput')获取页面中所有带有#cellInput标记的输入框,形成可查询的列表。 - 计算当前输入框在列表中的全局索引:
行索引 × 列数 + 当前列索引。 - 根据左右箭头操作,获取相邻位置的输入框元素,调用
nativeElement.focus()完成焦点切换。
内容的提问来源于stack exchange,提问作者bunnap
相关产品推荐
相关产品推荐

