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
相关产品推荐
相关产品推荐

