Angular通用动态列表格多列自定义filterPredicate实现求助
动态列通用表格的多列过滤实现方案
我需要实现一个通用Angular Material表格组件,核心需求是:
- 接收
tableColumns(动态列配置)和dataSource(原始数据)作为@Input() - 支持为每列添加独立的过滤输入框
- 已完成过滤表单的FormGroup初始化,能获取到各列的过滤值,但不清楚如何基于动态列实现通用过滤逻辑。试过管道和网上的固定列过滤方案,但都不适用动态列场景。
当前代码实现
HTML模板
<table mat-table [dataSource]="tableDataSource"> <ng-container *ngFor="let col of tableColumns; let i = index" [matColumnDef]="col.key"> <ng-container> <th class="header" mat-header-cell *matHeaderCellDef> <span *ngIf="!col.config"> {{ col['display'] }} </span> <form [formGroup]="form"> <mat-form-field *ngIf="!col.config" class="filter"> <input matInput placeholder="Filter" formControlName="{{tableColumns[i].key}}"> </mat-form-field> </form> </th> <td mat-cell *matCellDef="let element; let row"> <ng-container> {{ element[col.key] }} </ng-container> </td> </ng-container> </ng-container> <tr mat-header-row *matHeaderRowDef="keys"></tr> <tr mat-row *matRowDef="let row; columns: keys"></tr> </table>
TS组件代码
import { Component, Input, OnInit } from '@angular/core'; import { FormGroup, FormControl } from '@angular/forms'; import { MatTableDataSource } from '@angular/material/table'; interface GenericTableColumn { key: string; display: string; config?: any; } @Component({ selector: 'app-generic-table', templateUrl: './generic-table.component.html', styleUrls: ['./generic-table.component.css'] }) export class GenericTableComponent implements OnInit { @Input() tableColumns: GenericTableColumn[] = [] @Input() dataSource: Array<object> = [] form!: FormGroup; tableDataSource!: MatTableDataSource<any>; keys!: string[]; ngOnInit(): void { this.keys = this.tableColumns.map(col => col.key); this.initFormControls(); this.initTableDataSource(); this.registerFormChangeListener(); } initFormControls() { const formGroup: FormGroup = new FormGroup({}); this.tableColumns.forEach((column) => { if (column.key !== 'actions') { const control: FormControl = new FormControl(''); formGroup.addControl(column.key, control); } }); this.form = formGroup; } }
示例数据与期望结果
原始数据源
const sampleDataSource = [ { "id": "1", "name": "someValue1", "someOtherKey": "someOtherValue" }, { "id": "2", "name": "someValue2", "someOtherKey": "someOtherValue2" }, { "id": "3", "name": "someValue3", "someOtherKey": "someOtherValue2" } ];
过滤表单值
const filterValues = { "id": "", "name": "someValue1", "someOtherKey": "someOtherValue2" };
期望过滤结果
const filteredResults = [ { "id": "1", "name": "someValue1", "someOtherKey": "someOtherValue" }, { "id": "2", "name": "someValue2", "someOtherKey": "someOtherValue2" } ];
完整解决方案
1. 初始化带过滤功能的数据源
添加initTableDataSource方法,将原始数据转为MatTableDataSource并配置动态过滤逻辑:
initTableDataSource() { this.tableDataSource = new MatTableDataSource(this.dataSource); // 自定义动态过滤谓词 this.tableDataSource.filterPredicate = (row: any, filter: string) => { const filterObj = JSON.parse(filter); // 遍历所有过滤条件,仅保留非空条件的匹配 return Object.keys(filterObj).every(key => { const filterValue = filterObj[key]; if (!filterValue) return true; // 不区分大小写的模糊匹配,可根据需求调整匹配规则 const rowValue = String(row[key]).toLowerCase(); return rowValue.includes(filterValue.toLowerCase()); }); }; }
2. 监听表单变化触发过滤
添加registerFormChangeListener方法,订阅表单值变化事件,触发表格过滤:
registerFormChangeListener() { this.form.valueChanges.subscribe(filterObj => { // 过滤掉不需要的列(如actions列) const validFilterObj = Object.fromEntries( Object.entries(filterObj).filter(([key]) => this.tableColumns.some(col => col.key === key && col.key !== 'actions') ) ); // 将过滤对象转为JSON字符串,传递给表格数据源 this.tableDataSource.filter = JSON.stringify(validFilterObj); }); }
3. 模板修正
将模板中的[dataSource]="dataSource"改为[dataSource]="tableDataSource",确保使用带过滤功能的数据源。
内容的提问来源于stack exchange,提问作者LaCodeM
相关产品推荐
相关产品推荐

