Angular 8中创建带分页字段的MatTable数据源遇TS2416错误如何解决?
解决MatTable数据源与后端分页集成的类型错误问题
问题根源
你遇到的TS2416错误核心在于**DataSource的泛型类型和connect方法返回值不匹配**:DataSource<T>要求connect返回Observable<T[]>(单条数据的数组),但你现在返回的是Observable<Samples>(包含数组和分页信息的对象),这就导致了类型冲突。
我们需要调整数据源的设计,既要满足MatTable对数据源的类型要求,又要保留分页所需的total、pageSize、pageIndex参数。
解决方案步骤
1. 重构SamplesDataSource
修改数据源的泛型为Sample,单独维护分页参数的Subject,确保connect返回正确的样本数组Observable:
import { DataSource, CollectionViewer } from '@angular/cdk/collections'; import { BehaviorSubject, Observable, of, catchError } from 'rxjs'; import { Sample, Samples, NO_SAMPLES } from '../models/sample.model'; import { SamplesService } from '../services/samples.service'; export class SamplesDataSource extends DataSource<Sample> { // 维护样本数组的Subject private samplesSubject = new BehaviorSubject<Sample[]>(NO_SAMPLES.samples); // 维护分页参数的Subject private totalSubject = new BehaviorSubject<number>(NO_SAMPLES.total); private pageSizeSubject = new BehaviorSubject<number>(NO_SAMPLES.pageSize); private pageIndexSubject = new BehaviorSubject<number>(NO_SAMPLES.pageIndex); // 暴露分页参数的Observable供组件使用 public total$ = this.totalSubject.asObservable(); public pageSize$ = this.pageSizeSubject.asObservable(); public pageIndex$ = this.pageIndexSubject.asObservable(); constructor(private samplesService: SamplesService) { super(); } // 现在返回的是Sample[]的Observable,符合DataSource要求 connect(collectionViewer: CollectionViewer): Observable<Sample[]> { return this.samplesSubject.asObservable(); } disconnect(collectionViewer: CollectionViewer): void { this.samplesSubject.complete(); this.totalSubject.complete(); this.pageSizeSubject.complete(); this.pageIndexSubject.complete(); } getSamples() { this.samplesService.getSamples().pipe( catchError(err => { console.error('获取样本失败:', err); // 错误时返回空的Samples结构,而不是空数组 return of(NO_SAMPLES); }) ).subscribe((response: Samples) => { // 更新样本数组 this.samplesSubject.next(response.samples); // 更新分页参数 this.totalSubject.next(response.total); this.pageSizeSubject.next(response.pageSize); this.pageIndexSubject.next(response.pageIndex); }); } // 可选:添加分页变更后的请求方法(比如页码、页大小变化时调用) getPaginatedSamples(pageIndex: number, pageSize: number) { this.samplesService.getSamples(pageIndex, pageSize).pipe( catchError(err => { console.error('分页获取样本失败:', err); return of(NO_SAMPLES); }) ).subscribe((response: Samples) => { this.samplesSubject.next(response.samples); this.totalSubject.next(response.total); this.pageSizeSubject.next(response.pageSize); this.pageIndexSubject.next(response.pageIndex); }); } }
2. 调整组件代码
在组件中使用数据源的Observable来绑定分页器参数,同时修正mat-table的dataSource绑定:
// App component.ts import { Component, OnInit } from '@angular/core'; import { SamplesDataSource } from './shared/data-sources/samples-data-source'; import { SamplesService } from './shared/services/samples.service'; export class AlertCasesComponent implements OnInit { samplesTableColumns: string[] = ['sampleId', 'sample']; samplesTablePageSizes: number[] = [10, 20, 50, 100]; samplesDataSource: SamplesDataSource; constructor(private samplesService: SamplesService) {} ngOnInit(): void { this.samplesDataSource = new SamplesDataSource(this.samplesService); this.samplesDataSource.getSamples(); } // 处理分页器变更事件 onPageChange(event: any) { this.samplesDataSource.getPaginatedSamples(event.pageIndex, event.pageSize); } }
3. 修改模板绑定
使用async管道绑定分页参数,同时mat-table直接绑定数据源实例:
<!-- App Component.html --> <mat-table class="..." [dataSource]="samplesDataSource"> <!-- 你的列和行实现 --> <ng-container matColumnDef="sampleId"> <mat-header-cell *matHeaderCellDef> 样本ID </mat-header-cell> <mat-cell *matCellDef="let sample"> {{sample.id}} </mat-cell> </ng-container> <ng-container matColumnDef="sample"> <mat-header-cell *matHeaderCellDef> 样本名称 </mat-header-cell> <mat-cell *matCellDef="let sample"> {{sample.name}} </mat-cell> </ng-container> <mat-header-row *matHeaderRowDef="samplesTableColumns"></mat-header-row> <mat-row *matRowDef="let row; columns: samplesTableColumns;"></mat-row> </mat-table> <mat-paginator [length]="samplesDataSource.total$ | async" [pageIndex]="samplesDataSource.pageIndex$ | async" [pageSize]="samplesDataSource.pageSize$ | async" [pageSizeOptions]="samplesTablePageSizes" showFirstLastButtons (page)="onPageChange($event)"> </mat-paginator>
关键说明
DataSource<Sample>:明确泛型为单个样本类型,让connect返回Sample[]的Observable,符合Angular CDK的类型要求。- 分页参数独立维护:通过单独的Subject保存
total、pageSize等参数,并暴露Observable给组件,配合async管道实现响应式绑定。 - 错误处理优化:catchError中返回
NO_SAMPLES而不是空数组,确保分页参数不会因为请求错误出现异常。
内容的提问来源于stack exchange,提问作者drunkZombie
相关产品推荐
相关产品推荐

