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
相关产品推荐
相关产品推荐

