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

Angular Material:如何让Selection List首个元素获得焦点

问题解决:Angular Material 列表第一个元素自动获取焦点

问题1:@ViewChild 获取 mat-selection-list 为空的原因及修复

你当前用ElementRef获取mat-selection-list并设置static: true的方式有误。动态渲染的列表在视图初始化阶段可能还未完成渲染,且应该使用Angular Material提供的MatSelectionList类型而非原生ElementRef来获取组件实例。

修复后的TS代码:

import { MatSelectionList } from '@angular/material/list';
// ...
@ViewChild('myList') matSelList: MatSelectionList;  

ngAfterViewInit(): void {
  // 确保动态列表渲染完成后执行
  setTimeout(() => {
    this.setFirstOptionFocus();
  });
}

private setFirstOptionFocus(): void {
  if (this.matSelList && this.matSelList.options.length > 0) {
    const firstOption = this.matSelList.options.first.nativeElement;
    firstOption.focus();
  }
}

关键调整点:

  • 将类型替换为MatSelectionList,它自带options属性可直接访问所有列表项实例
  • 移除static: true,默认static: false会在视图初始化完成后获取组件,适配动态内容场景
  • 用ngAfterViewInit替代ngAfterViewChecked,避免不必要的频繁触发

问题2:更优雅的获取第一个mat-list-option的方法

方式1:模板标记第一个元素

在@for循环中给第一个列表项添加模板引用变量,直接通过@ViewChild获取:
模板代码:

<mat-selection-list #myList>
  @for (prodCat of list; track prodCat.id; let first = $first) {
    <mat-list-option #firstOption *ngIf="first" togglePosition="before">
      {{ prodCat.name }}
    </mat-list-option>
    <mat-list-option *ngIf="!first" togglePosition="before">
      {{ prodCat.name }}
    </mat-list-option>
  }
</mat-selection-list>

TS代码:

@ViewChild('firstOption') firstOption: ElementRef<HTMLElement>;

ngAfterViewInit(): void {
  setTimeout(() => {
    this.firstOption?.nativeElement.focus();
  });
}

方式2:监听列表项变化(适配数据动态更新场景)

通过ViewChildren获取所有列表项,监听列表变化后设置焦点:

import { MatListOption } from '@angular/material/list';
import { ViewChildren, QueryList } from '@angular/core';
// ...
@ViewChildren(MatListOption) listOptions: QueryList<MatListOption>;

ngAfterViewInit(): void {
  this.listOptions.changes.subscribe(() => {
    if (this.listOptions.length > 0) {
      this.listOptions.first.nativeElement.focus();
    }
  });
}

额外注意事项

  • 确保list数据在ngOnInit或更早的生命周期中完成赋值,否则@for循环不会渲染任何列表项
  • 调用focus()前需保证元素已挂载到DOM,因此使用setTimeout或监听QueryList变化是必要的

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 01:43:17