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

如何为Angular多选列表框添加上下键键盘导航?

Angular多选列表添加上下键键盘导航实现方法

当然可以实现,下面是具体的修改方案,分为HTML模板调整和组件逻辑实现两部分:

一、修改HTML模板

给外层容器添加键盘事件监听和可聚焦属性,同时优化子项的可访问性:

<div 
  tabindex="0"
  (keydown)="handleKeyDown($event)"
  class="list-container"
>
  <div
    *ngFor="let tag of tags; let index=index"
    [class.selectedRow]="rowIsSelected(tag.id)"
    [class.focused]="index === currentFocusIndex"
    (click)="onRowClick(tag.id, index, $event)"
    tabindex="-1"
    [attr.aria-selected]="rowIsSelected(tag.id)"
  >
    <span>{{ tag.text }}</span>
  </div>
</div>

二、实现组件逻辑

在对应的Angular组件类中添加键盘导航相关的状态和方法:

import { Component } from '@angular/core';

@Component({
  // 组件元数据,比如selector、templateUrl等
})
export class TagListComponent {
  tags = [/* 你的标签数据,示例:{id: 1, text: '标签1'}, {id: 2, text: '标签2'} */];
  selectedIds: number[] = [];
  currentFocusIndex = -1;

  // 判断行是否选中
  rowIsSelected(tagId: number): boolean {
    return this.selectedIds.includes(tagId);
  }

  // 处理行点击事件
  onRowClick(tagId: number, index: number, event: MouseEvent): void {
    // 切换选中状态
    const idIndex = this.selectedIds.indexOf(tagId);
    if (idIndex > -1) {
      this.selectedIds.splice(idIndex, 1);
    } else {
      this.selectedIds.push(tagId);
    }
    // 更新当前聚焦索引
    this.currentFocusIndex = index;
    // 聚焦当前行
    const rowElement = document.querySelector(`div[tabindex="-1"]:nth-child(${index + 1})`);
    rowElement?.focus();
  }

  // 处理键盘事件
  handleKeyDown(event: KeyboardEvent): void {
    if (this.tags.length === 0) return;

    switch (event.key) {
      case 'ArrowUp':
        event.preventDefault(); // 阻止页面滚动
        this.currentFocusIndex = Math.max(0, this.currentFocusIndex - 1);
        this.focusCurrentRow();
        break;
      case 'ArrowDown':
        event.preventDefault(); // 阻止页面滚动
        this.currentFocusIndex = Math.min(this.tags.length - 1, this.currentFocusIndex + 1);
        this.focusCurrentRow();
        break;
      case 'Enter':
      case ' ':
        event.preventDefault();
        // 按下回车或空格时切换当前聚焦项的选中状态
        if (this.currentFocusIndex > -1) {
          const tag = this.tags[this.currentFocusIndex];
          const idIndex = this.selectedIds.indexOf(tag.id);
          if (idIndex > -1) {
            this.selectedIds.splice(idIndex, 1);
          } else {
            this.selectedIds.push(tag.id);
          }
        }
        break;
    }
  }

  // 聚焦当前行并滚动到视图
  private focusCurrentRow(): void {
    if (this.currentFocusIndex === -1) return;
    const rowElement = document.querySelector(`div[tabindex="-1"]:nth-child(${this.currentFocusIndex + 1})`);
    if (rowElement) {
      rowElement.focus();
      rowElement.scrollIntoView({ block: 'nearest', behavior: 'smooth' });
    }
  }
}

三、样式优化(可选)

给聚焦状态添加样式,让用户更清楚当前导航项:

.list-container {
  outline: none; /* 移除默认聚焦边框,可自定义 */
  max-height: 300px;
  overflow-y: auto;
}

.list-container > div.focused {
  background-color: #e0e0e0; /* 自定义聚焦背景色 */
  outline: 2px solid #2196f3; /* 自定义聚焦边框 */
}

.selectedRow {
  background-color: #f5f5f5; /* 你的选中样式 */
}

关键说明

  • tabindex="0"让外层容器可以通过Tab键聚焦,从而接收键盘事件;子项的tabindex="-1"允许通过JS聚焦,但不会被Tab键选中。
  • 区分选中状态(点击后标记)和聚焦状态(键盘导航的当前项),避免混淆。
  • scrollIntoView确保当前聚焦项在容器可视范围内,防止滚动后找不到导航项。
  • 支持回车/空格切换选中状态,符合无障碍设计规范。

内容的提问来源于stack exchange,提问作者Mark

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 17:41:24