Angular mat-autocomplete面板首次聚焦不展开问题求助
问题排查与解决方案
问题原因分析
异步数据加载与过滤流初始化时机冲突
你的onFetchTPA是异步HTTP请求,searchFiltertpa在ngOnInit中直接调用时,tpaDetails还未被接口返回的数据赋值。此时filteredTPA流中startWith('')触发过滤逻辑时,this.tpaDetails.slice()返回空数组,导致面板无选项可展示,自然不会展开。mat-autocomplete默认无聚焦展开行为
Angular Material的mat-autocomplete组件默认不会在输入框聚焦时自动打开面板,只有当输入框值变化(输入文本)时才会触发过滤流并展示面板。
解决方案
1. 同步异步数据与过滤流
使用BehaviorSubject包装tpaDetails,确保过滤流能监听数据加载完成后的更新:
修改class.ts代码:
import { BehaviorSubject, combineLatest } from 'rxjs'; import { map, startWith } from 'rxjs/operators'; // 新增BehaviorSubject用于监听tpa数据变化 private tpaDetailsSubject = new BehaviorSubject<any[]>([]); onFetchTPA() { this.validation_dialog_box = true; this.fr_write_service.onFetchTPA().subscribe((data) => { const responseData = JSON.parse(data); this.tpaDetails = responseData?.sort((a, b) => { if (a.tpaName < b.tpaName) return -1; if (a.tpaName > b.tpaName) return 1; return 0; }); // 将加载完成的数据发送到Subject this.tpaDetailsSubject.next(this.tpaDetails); this.validation_dialog_box = false; }, (error) => { this.errorPopup(error); }); } searchFiltertpa(formDetails) { const tpaCntrl = formDetails.get('tpa'); if (tpaCntrl) { // 结合输入框值变化和数据Subject的流 this.filteredTPA = combineLatest([ tpaCntrl.valueChanges.pipe(startWith('')), this.tpaDetailsSubject.asObservable() ]).pipe( map(([value, tpaList]) => { // 处理选中对象的情况,提取搜索关键词 const searchTerm = typeof value === 'string' ? value : value?.tpaName || ''; return searchTerm ? this.filtertpa(searchTerm, tpaList) : tpaList.slice(); }) ); } } // 修改filtertpa方法,接收当前的tpa列表作为参数 filtertpa(tpaData: any, tpaList: any[]) { const arr = tpaList.filter( (tpa) => tpa.tpaName.toLowerCase().indexOf(tpaData.toLowerCase()) === 0 ); return arr.length ? arr : [{ tpaName: 'No Item found' }]; }
2. 添加聚焦触发面板展开逻辑
在输入框上绑定focus事件,手动调用面板的open()方法:
修改HTML代码:
<mat-form-field class="width"> <input type="text" formControlName="tpa" matInput [matAutocomplete]="tpaAuto" (focus)="openPanel(tpaAuto)" /> <mat-autocomplete #tpaAuto="matAutocomplete" [displayWith]="displayTpa.bind(this)"> <mat-option *ngFor="let data of exportPdfInstance.filteredTPA | async" [value]="data"> <span>{{ data.tpaName }}</span> </mat-option> </mat-autocomplete> </mat-form-field>
在组件component.ts中添加openPanel方法:
import { MatAutocomplete } from '@angular/material/autocomplete'; // ... openPanel(panel: MatAutocomplete) { panel.open(); }
3. 第二个autocomplete组件的适配
对第二个mat-autocomplete组件执行相同逻辑:
- 用
BehaviorSubject包装对应的数据列表 - 修改其过滤方法为
combineLatest模式 - 在输入框上绑定
(focus)="openPanel(xxxAuto)",传入对应的面板引用
内容的提问来源于stack exchange,提问作者Danny
相关产品推荐
相关产品推荐

