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

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代码

  1. 导入所需依赖:
import { Component, OnInit, ViewChildren, QueryList, ElementRef } from '@angular/core';
import { VERSION } from '@angular/core';
import { MatTableDataSource } from '@angular/material/table';
  1. 添加ViewChildren收集所有输入框:
@ViewChildren('cellInput') cellInputs!: QueryList<ElementRef<HTMLInputElement>>;
  1. 修改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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 05:35:19