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

Angular Material表格分页与表单查询联动API调用问题

解决方案

核心思路是以表单提交事件作为API调用的触发起点,后续分页变化时自动携带最新的表单参数发起请求,既避免页面加载时的无参数调用,又满足分页更新时重新请求的需求。

具体实现步骤

1. 组件逻辑实现

import { Component, ViewChild, AfterViewInit } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { MatPaginator, PageEvent } from '@angular/material/paginator';
import { Subject, Observable, concat, of, fromEvent } from 'rxjs';
import { filter, switchMap, distinctUntilChanged } from 'rxjs/operators';
import { ApiService } from './api.service'; // 替换为你的API服务

@Component({
  selector: 'app-search-table',
  templateUrl: './search-table.component.html',
  styleUrls: ['./search-table.component.css']
})
export class SearchTableComponent implements AfterViewInit {
  searchForm: FormGroup;
  @ViewChild(MatPaginator) paginator!: MatPaginator;
  
  // 提交触发信号
  private searchTrigger$ = new Subject<void>();
  // 组合后的请求参数流
  private requestParams$!: Observable<{
    formValue: any;
    page: number;
    pageSize: number;
  }>;
  // 表格数据流
  data$!: Observable<any[]>; // 替换为你的数据类型

  constructor(private fb: FormBuilder, private apiService: ApiService) {
    // 初始化表单
    this.searchForm = this.fb.group({
      field1: ['', Validators.required],
      field2: [''],
      field3: ['']
    });
  }

  ngAfterViewInit(): void {
    // 转换分页事件为Observable
    const pageChange$ = fromEvent(this.paginator.page);

    // 构建请求参数流
    this.requestParams$ = this.searchTrigger$.pipe(
      // 过滤无效表单
      filter(() => this.searchForm.valid),
      // 首次触发后,合并初始分页参数和后续分页变化
      switchMap(() => {
        const initialParams = {
          formValue: this.searchForm.value,
          page: this.paginator.pageIndex,
          pageSize: this.paginator.pageSize
        };
        return concat(
          of(initialParams),
          pageChange$.pipe(
            map((event: PageEvent) => ({
              formValue: this.searchForm.value,
              page: event.pageIndex,
              pageSize: event.pageSize
            }))
          )
        );
      }),
      // 避免重复请求(参数无变化时跳过)
      distinctUntilChanged((prev, curr) => 
        JSON.stringify(prev) === JSON.stringify(curr)
      )
    );

    // 发起API请求
    this.data$ = this.requestParams$.pipe(
      switchMap(params => 
        this.apiService.fetchData(
          params.formValue, 
          params.page, 
          params.pageSize
        )
      )
    );
  }

  // 提交按钮点击事件
  onSubmit(): void {
    this.searchTrigger$.next();
  }
}

2. 模板代码

<form [formGroup]="searchForm" (ngSubmit)="onSubmit()">
  <mat-form-field>
    <input matInput formControlName="field1" placeholder="字段1(必填)" required>
    <mat-error *ngIf="searchForm.get('field1')?.invalid">此字段为必填项</mat-error>
  </mat-form-field>
  <mat-form-field>
    <input matInput formControlName="field2" placeholder="字段2">
  </mat-form-field>
  <mat-form-field>
    <input matInput formControlName="field3" placeholder="字段3">
  </mat-form-field>
  <button mat-raised-button color="primary" type="submit" [disabled]="!searchForm.valid">
    提交查询
  </button>
</form>

<mat-table [dataSource]="data$ | async" class="mat-elevation-z8">
  <!-- 替换为你的表格列定义 -->
  <ng-container matColumnDef="field1">
    <mat-header-cell *matHeaderCellDef>字段1</mat-header-cell>
    <mat-cell *matCellDef="let element">{{element.field1}}</mat-cell>
  </ng-container>
  <!-- 其他列... -->
  <mat-header-row *matHeaderRowDef="displayedColumns"></mat-header-row>
  <mat-row *matRowDef="let row; columns: displayedColumns;"></mat-row>
</mat-table>

<mat-paginator 
  [pageSizeOptions]="[5, 10, 20]" 
  showFirstLastButtons
  aria-label="分页">
</mat-paginator>

方案优势

  • 严格触发条件:仅在表单验证通过且用户点击提交按钮后,才会发起首次API请求,彻底避免页面加载时的无参数调用问题。
  • 自动响应分页变化:分页状态更新时,会自动携带当前最新的表单参数重新请求数据,无需手动处理分页事件。
  • 响应式风格:完全基于RxJS的响应式流实现,符合Angular官方推荐的编程模式,和官网table-http示例思路一致但增加了表单触发的限制。
  • 避免重复请求:通过distinctUntilChanged过滤参数未变化的情况,减少不必要的API调用。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 20:43:27