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

Angular 5 Material HTTP数据表格后端分页实现问询

嘿,我来帮你搞定这个基于后端链接的Angular Material分页问题!官方文档对这种非内存分页的场景确实讲得不够细,我一步步给你拆解实现步骤:

实现基于后端分页链接的Angular Material表格分页

这种模式属于基于游标/链接的分页,我们需要绕过MatTableDataSource的默认内存分页逻辑,自己处理分页请求和数据更新。

1. 先完善你的JobService

首先确保你的服务能处理初始请求和后续的分页请求,返回包含数据、下一页链接的结构(如果后端能返回总条数就更好,方便分页器显示总页数):

// job.service.ts
import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs';

// 定义后端返回的响应结构
interface JobPaginationResponse {
  data: any[];       // 当前页的50条数据
  next: string | null; // 下一页的请求链接(没有下一页则为null)
  totalCount?: number; // 可选:总数据条数,用于分页器显示总页数
}

@Injectable({ providedIn: 'root' })
export class JobService {
  constructor(private http: HttpClient) {}

  // 支持传入自定义链接,默认请求第一页
  getJobs(pageUrl: string = '/api/jobs?limit=50'): Observable<JobPaginationResponse> {
    return this.http.get<JobPaginationResponse>(pageUrl);
  }
}

2. 改造ListComponent逻辑

接下来修改你的组件,添加分页相关的变量和事件监听:

// list.component.ts
import { Component, OnInit, ViewChild } from '@angular/core';
import { MatPaginator } from '@angular/material/paginator';
import { JobService } from './../../core/services/job/job.service';
import { catchError } from 'rxjs/operators';
import { of } from 'rxjs';

@Component({
  selector: 'app-list',
  templateUrl: './list.component.html',
  styleUrls: ['./list.component.scss']
})
export class ListComponent implements OnInit {
  displayedColumns: string[] = ['Identifier', 'ProductName', 'Status', 'DateTime'];
  jobList: any[] = []; // 存储当前页的job数据
  nextPageUrl: string | null = null;
  totalJobCount = 0; // 总数据条数(如果后端返回的话)

  @ViewChild(MatPaginator) paginator!: MatPaginator;

  constructor(private jobService: JobService) {}

  ngOnInit(): void {
    // 加载初始数据
    this.loadFirstPage();
    // 监听分页器的页码切换事件
    this.paginator.page.subscribe(() => {
      this.loadTargetPage();
    });
  }

  loadFirstPage(): void {
    this.jobService.getJobs()
      .pipe(
        // 简单处理请求错误,避免页面卡住
        catchError(err => {
          console.error('加载数据失败:', err);
          return of({ data: [], next: null });
        })
      )
      .subscribe(response => {
        this.jobList = response.data;
        this.nextPageUrl = response.next;
        // 如果后端返回总条数,更新分页器的总长度
        if (response.totalCount) {
          this.totalJobCount = response.totalCount;
          this.paginator.length = this.totalJobCount;
        }
        // 把分页器的每页条数设为和后端一致(50条)
        this.paginator.pageSize = 50;
      });
  }

  loadTargetPage(): void {
    // 没有下一页链接,或者是第一页且已经加载过,就不请求
    if (!this.nextPageUrl && this.paginator.pageIndex > 0) return;

    this.jobService.getJobs(this.nextPageUrl!)
      .pipe(catchError(err => {
        console.error('加载分页数据失败:', err);
        return of({ data: [], next: null });
      }))
      .subscribe(response => {
        this.jobList = response.data;
        this.nextPageUrl = response.next;
        // 如果你需要的是"加载更多"(保留之前的数据),而不是切换页面,
        // 可以把上面的赋值改成:this.jobList = [...this.jobList, ...response.data];
        // 同时手动更新页码:this.paginator.pageIndex = this.paginator.pageIndex + 1;
      });
  }

  show(row: any): void {
    // 你的点击行逻辑
  }
}

3. 调整模板文件

修改模板,把表格数据源绑定到我们自己维护的jobList,同时配置分页器的参数:

<!-- list.component.html -->
<div class="example-container mat-elevation-z8">
  <mat-table #table [dataSource]="jobList">
    <ng-container matColumnDef="Identifier">
      <mat-header-cell *matHeaderCellDef>Identifier</mat-header-cell>
      <mat-cell *matCellDef="let job">{{job.job_id}}</mat-cell>
    </ng-container>
    <ng-container matColumnDef="ProductName">
      <mat-header-cell *matHeaderCellDef>Product Name</mat-header-cell>
      <mat-cell *matCellDef="let job">{{job.product_id}}</mat-cell>
    </ng-container>
    <ng-container matColumnDef="Status">
      <mat-header-cell *matHeaderCellDef>Status</mat-header-cell>
      <mat-cell *matCellDef="let job">{{job.status}}</mat-cell>
    </ng-container>
    <ng-container matColumnDef="DateTime">
      <mat-header-cell *matHeaderCellDef>Date & Time</mat-header-cell>
      <mat-cell *matCellDef="let job">{{job.reg_time | date:'d/MMM/y HH:mm'}}</mat-cell>
    </ng-container>
    <mat-header-row *matHeaderRowDef="displayedColumns"></mat-header-row>
    <mat-row *matRowDef="let row; columns: displayedColumns;" (click)="show(row)"></mat-row>
  </mat-table>

  <!-- 配置分页器:如果后端没返回总条数,可以去掉[length],只显示上下页按钮 -->
  <mat-paginator 
    [pageSize]="50"
    [length]="totalJobCount"
    [showFirstLastButtons]="true"
    [disabled]="(!nextPageUrl && paginator.pageIndex !== 0) || (paginator.pageIndex === 0 && !jobList.length)">
  </mat-paginator>
</div>

几个关键细节

  • 切换页面 vs 加载更多:上面的代码是切换页面(每次请求替换当前数据),如果需要滚动加载保留之前的数据,修改loadTargetPage里的数据赋值方式即可。
  • 错误处理:添加了简单的错误捕获,避免请求失败导致页面无响应,你可以根据需求改成更友好的提示。
  • 分页器状态:通过disabled属性控制分页器按钮的可用性,避免无效请求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 03:56:30