如何为Angular Table CDK配置对接远程数据源加载表格数据
Angular Material Table 对接远程数据源的正确实现方式
你当前使用的是Material Schematic默认生成的面向本地静态数据的DataSource模板,只需要针对性调整connect逻辑即可对接远程服务,不需要额外的变通方案,以下分两种常用场景给出实现:
场景1:数据量较小,一次性拉取全量数据,本地处理分页/排序
第一步:改造DataSource类
export class ExampleTableDataSource extends DataSource<ExampleTableItem> { data: ExampleTableItem[] = []; paginator: MatPaginator | undefined; sort: MatSort | undefined; // 注入远程请求服务 constructor(private exampleService: ExampleService) { super(); } connect(): Observable<ExampleTableItem[]> { if (this.paginator && this.sort) { // 合并三个触发数据更新的事件:初始加载、分页切换、排序切换 return merge( // 初始触发信号 of(void 0), this.paginator.page, this.sort.sortChange ).pipe( // 切换到数据处理流 switchMap(() => { // 首次加载时调用远程接口拉取全量数据 if (this.data.length === 0) { return this.exampleService.getAll().pipe( tap(res => this.data = res) ) } // 后续分页/排序直接用本地已缓存的数据 return of(this.data); }), // 对数据做排序、分页处理 map(data => this.getPagedData(this.getSortedData([...data]))) ); } throw Error('请在connect前为DataSource设置paginator和sort实例'); } disconnect(): void {} // 原有getPagedData、getSortedData方法保留即可 private getPagedData(data: ExampleTableItem[]): ExampleTableItem[] { if (this.paginator) { const startIndex = this.paginator.pageIndex * this.paginator.pageSize; return data.slice(startIndex, startIndex + this.paginator.pageSize); } return data; } private getSortedData(data: ExampleTableItem[]): ExampleTableItem[] { if (!this.sort || !this.sort.active || this.sort.direction === '') { return data; } return data.sort((a, b) => { const isAsc = this.sort.direction === 'asc'; switch (this.sort.active) { case 'name': return compare(a.name, b.name, isAsc); case 'id': return compare(+a.id, +b.id, isAsc); default: return 0; } }); } } // 原有比较函数保留 function compare(a: number | string, b: number | string, isAsc: boolean) { return (a < b ? -1 : 1) * (isAsc ? 1 : -1); }
第二步:在表格组件中初始化DataSource
export class ExampleTableComponent implements AfterViewInit { @ViewChild(MatPaginator) paginator!: MatPaginator; @ViewChild(MatSort) sort!: MatSort; dataSource: ExampleTableDataSource; // 注入ExampleService后传给DataSource constructor(private exampleService: ExampleService) { this.dataSource = new ExampleTableDataSource(exampleService); } ngAfterViewInit() { this.dataSource.paginator = this.paginator; this.dataSource.sort = this.sort; } }
场景2:数据量较大,服务端处理分页/排序
这种场景下每次分页、排序变更都会触发远程请求,将分页参数、排序参数传给后端,由后端返回对应页的数据:
第一步:调整ExampleService的getAll方法,支持传参
getAll(params: {pageIndex: number, pageSize: number, sortField: string, sortOrder: 'asc'|'desc'|''}): Observable<{total: number, list: ExampleTableItem[]}> { // 将参数拼接到请求中传给后端 return this.http.get<{total: number, list: ExampleTableItem[]}>(url, {params}); }
第二步:改造DataSource类,移除本地分页/排序逻辑
export class ExampleTableDataSource extends DataSource<ExampleTableItem> { paginator: MatPaginator | undefined; sort: MatSort | undefined; private totalCount = 0; constructor(private exampleService: ExampleService) { super(); } connect(): Observable<ExampleTableItem[]> { if (this.paginator && this.sort) { return merge( of(void 0), this.paginator.page, this.sort.sortChange ).pipe( switchMap(() => { // 组装请求参数 const params = { pageIndex: this.paginator.pageIndex, pageSize: this.paginator.pageSize, sortField: this.sort.active, sortOrder: this.sort.direction } return this.exampleService.getAll(params); }), tap(res => { // 更新分页器总条数 this.totalCount = res.total; if (this.paginator) { this.paginator.length = res.total; } }), map(res => res.list) ); } throw Error('请在connect前为DataSource设置paginator和sort实例'); } disconnect(): void {} }
组件初始化逻辑和场景1一致即可。
内容的提问来源于stack exchange,提问作者Aeseir
相关产品推荐
相关产品推荐

