You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Angular Mat Table服务端分页异常:分页器无法启用

问题描述

我基于Angular Material Table实现了一个服务端取数的表格组件,数据通过父组件的@Input() properties: any;传入子组件作为数据源。目前要实现服务端分页,已配置(page)="onChangePage($event)"事件,该事件可获取分页参数并传递给父组件调用API,但分页器的翻页箭头处于禁用状态,无法切换到下一页。检查代码后未发现明显问题,希望得到问题排查思路或解决方案。

相关代码

HTML代码

<table (matSortChange)="sortData($event)" mat-table [dataSource]="dataSource" matSort id="table" cdkDropList cdkDropListOrientation="horizontal" (cdkDropListDropped)="drop($event)">
    <ng-container matColumnDef={{col.matColumnDef}} *ngFor="let col of gridColumns">
        <th mat-header-cell *matHeaderCellDef cdkDrag mat-sort-header> {{col.columnHeader}} </th>
        <td mat-cell *matCellDef="let row">
            <span *ngIf="col.columnHeader !== 'Property Name'">
                {{(col.value(row) !== 'null')? col.value(row) : '-'}}
            </span>
            <span *ngIf="col.columnHeader === 'Property Name'">
                {{(col.value(row) !== 'null')? col.value(row) : '-'}}
                <br>
                <span class="property-sub-content">{{row.city}}, {{row.state}}</span>
            </span>
        </td>
    </ng-container>
    <tr mat-header-row *matHeaderRowDef="displayedColumns;"></tr>
    <tr mat-row *matRowDef="let row; columns: displayedColumns;" (click)="getPlaceDetails(row.propertyAccountId)"></tr>
</table>
</div>
<mat-paginator [length]="properties.totalItemCount" [pageSize]="properties.lastItemOnPage" [pageSizeOptions]="[20, 50, 100]" showFirstLastButtons (page)="onChangePage($event)"></mat-paginator>

TS代码片段

dataSource = new MatTableDataSource<any>();
@ViewChild(MatSort) sort: MatSort;
@ViewChild(MatPaginator) paginator: MatPaginator;

@Input() properties: any;

constructor(private iterableDiffers: IterableDiffers, private _route: Router, private _storageService: StorageService) {
    this.iterableDiffer = iterableDiffers.find([]).create(null);
}

ngDoCheck() {
    let changes = this.iterableDiffer.diff(this.properties);
    if (changes) {
        let dataSource: any;
        dataSource = JSON.stringify(this.properties);
        dataSource = JSON.parse(dataSource);
        dataSource = dataSource.filter(x => x.propertyAccountId);
        this.dataSource.data = dataSource;

        if(this.dataSource.data) {
            setTimeout(()=>{this.initFreezeTableHeader();},1000);   
        }
    }
}

ngAfterViewInit() {
    this.dataSource.sort = this.sort;
    this.dataSource.paginator = this.paginator;
}

sortData(event) {
    console.log('EVENT' , event)
}

ngOnInit(): void {    
    const currAcct = this._storageService.getCurrAcct();
    this.currentAccountId = JSON.parse(currAcct).accountId;
    this.accountName = JSON.parse(currAcct).accountName;
    this.gridColumns = PROPERTIES.GRID_COLUMNS[this.accountName];
    this.displayedColumns = this.gridColumns.map(g => g.matColumnDef);   
}

ngOnDestroy(): void {
    let customDashBoardSelected = document.querySelector('#dashboard-content-container') as HTMLElement | null;
        customDashBoardSelected.style.height = '100%';
}

drop(event: CdkDragDrop<string[]>) {
    moveItemInArray(this.displayedColumns, event.previousIndex, event.currentIndex);
}

applyFilter(event: Event) {
    const filterValue = (event.target as HTMLInputElement).value;
    this.dataSource.filter = filterValue.trim().toLowerCase();
}

getPlaceDetails(propertyAccountId: string) {    
    this._route.navigateByUrl(`/properties/${propertyAccountId}`);
}

onChangePage(event:any){        
    this.filterProperties.emit(event)
    console.log('event' , event)
}

properties示例数据(父组件传入的数据源)

{
    "firstItemOnPage": 1,
    "lastItemOnPage": 20,
    "totalItemCount": 159,
    "items": [
        {
            "id": 4619,
            "propertyName": "A Drug Store",
            "propertyAccountId": "10323202-S",
            "addressLine1": "3255 VICKSBURG LN N"
        },
        {
            "id": 9868,
            "propertyName": "B Drug Store",
            "propertyAccountId": "23210187-S",
            "addressLine1": "900 MAIN AVE"
        }
    ]
}
问题排查与解决方案
  • 分页器pageSize绑定错误:当前[pageSize]="properties.lastItemOnPage"绑定的是当前页最后一条数据的序号(如第一页是20),但pageSize需要的是每页显示的条数。应改为绑定固定值(如20)或从父组件传入专门的pageSize字段,而非lastItemOnPage。
  • 禁用MatTableDataSource的客户端分页:服务端分页场景下,不能设置this.dataSource.paginator = this.paginator;,否则MatTable会自动计算客户端分页状态,与服务端返回的分页信息冲突,导致分页按钮禁用。需删除ngAfterViewInit中的该赋值语句。
  • 数据源赋值错误:ngDoCheck中错误地对整个properties对象执行filter操作(properties是包含分页信息的对象,不是数组),应该取properties.items作为表格数据源:
    // 替换原ngDoCheck中的数据源赋值逻辑
    this.dataSource.data = this.properties.items.filter(x => x.propertyAccountId);
    
  • 同步分页器当前页索引:服务端返回新页数据后,需手动同步分页器的pageIndex(注意是0基索引),比如父组件返回第二页数据时,设置this.paginator.pageIndex = 1;,确保分页器状态与服务端数据匹配。

内容的提问来源于stack exchange,提问作者Tim Launders

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.11 03:21:10