Angular Mat Table异步代码更新列数据不生效问题求助
Angular Mat Table异步更新行数据不即时显示的解决方法
问题根源
硬编码同步赋值时,数据修改发生在数据源订阅的同步流程里,Mat Table能及时感知变化并渲染;但异步请求完成后再赋值时,当前数据源的订阅周期已经结束,直接修改对象属性不会触发Mat Table的变更检测,只有分页切换(触发数据源重新加载)才会显示更新后的数据。
解决方案
方案1:手动触发数据源变更通知
如果你的currentDataSource是MatTableDataSource,可以在所有异步请求完成后,通过重新赋值data属性触发渲染:
this.tableGenerator.currentDataSource.connect().subscribe(async (data) => { // 等待所有异步请求完成 await Promise.all(data.map(async (prop) => { if (prop.eventNo && !prop.evtDescription) { const event = await this.eventsService .getEventByNo(prop.eventNo) .pipe(first()) .toPromise(); prop['evtDescription'] = event.description; } })); // 用展开运算符创建新数组,触发引用变更 this.tableGenerator.currentDataSource.data = [...data]; });
方案2:用RxJS流提前整合异步数据
把异步请求整合到数据流中,让Mat Table直接拿到完整数据:
import { forkJoin, of, switchMap } from 'rxjs'; import { first, map } from 'rxjs/operators'; // ... this.tableGenerator.currentDataSource.connect().pipe( switchMap(data => { const observables = data.map(prop => { if (prop.eventNo && !prop.evtDescription) { return this.eventsService.getEventByNo(prop.eventNo).pipe( first(), map(event => ({...prop, evtDescription: event.description})) ); } return of(prop); }); return forkJoin(observables); }) ).subscribe(updatedData => { this.tableGenerator.currentDataSource.data = updatedData; });
方案3:创建新对象触发变更(适用于不可变数据场景)
如果数据对象是不可变类型,直接修改属性无效,需要替换原对象:
await Promise.all(data.map(async (prop) => { if (prop.eventNo && !prop.evtDescription) { const event = await this.eventsService .getEventByNo(prop.eventNo) .pipe(first()) .toPromise(); // 找到原对象索引,替换为新对象 const index = data.indexOf(prop); data[index] = {...prop, evtDescription: event.description}; } })); this.tableGenerator.currentDataSource.data = [...data];
注意事项
- 不要在
map中使用async/await却不等待结果,必须用Promise.all处理所有异步任务 - 直接修改数组元素的属性不会触发变更检测,必须通过修改数组引用或调用数据源的更新方法强制刷新
内容的提问来源于stack exchange,提问作者Timba
相关产品推荐
相关产品推荐

