基于接口过滤Angular Material数据表数据源的实现方案
Angular Material DataTable 对接IAZEFilter多条件过滤实现方案
完全可以基于你定义的IAZEFilter接口实现过滤,不用额外引入工具,直接利用MatTableDataSource原生的自定义过滤谓词能力即可,实现步骤:
- 重写数据源的
filterPredicate属性
MatTableDataSource默认是全局单字符串模糊匹配,我们把匹配逻辑改成按IAZEFilter的字段逐规则判断就行,注意因为原生filter属性只接收字符串,传参时把过滤对象序列化即可,谓词内反序列化后做判断:
// 表格行数据结构,根据实际业务字段替换即可 interface ITableRowData { globalSearchField: string; // 参与全局搜索的字段拼接值,比如把名称、单号、备注等需要搜的字段提前拼好 recordDate: string; // 对应时间范围匹配的业务日期字段 buchungsart: number; // 对应记账类型字段 status: number; // 对应状态字段 [key: string]: any; // 其他业务字段 } // 初始化数据源时绑定自定义过滤规则 dataSource = new MatTableDataSource<ITableRowData>(yourFullDataList); dataSource.filterPredicate = (row: ITableRowData, filterStr: string): boolean => { const filterRules: IAZEFilter = JSON.parse(filterStr); let isMatch = true; // 全局搜索匹配 if (filterRules.fiSearch?.trim()) { const keyword = filterRules.fiSearch.trim().toLowerCase(); isMatch = isMatch && row.globalSearchField.toLowerCase().includes(keyword); } // 时间范围匹配 if (filterRules.fiZeitraumVon) { const rowTs = new Date(row.recordDate).getTime(); const startTs = new Date(filterRules.fiZeitraumVon).getTime(); isMatch = isMatch && rowTs >= startTs; } if (filterRules.fiZeitraumBis) { const rowTs = new Date(row.recordDate).getTime(); const endTs = new Date(filterRules.fiZeitraumBis).getTime(); isMatch = isMatch && rowTs <= endTs; } // 多选记账类型匹配 if (filterRules.fiBuchungsart?.length) { isMatch = isMatch && filterRules.fiBuchungsart.includes(row.buchungsart); } // 多选状态匹配 if (filterRules.fiStatus?.length) { isMatch = isMatch && filterRules.fiStatus.includes(row.status); } return isMatch; };
你定义的IAZEFilter接口不用做任何修改,直接复用即可:
export interface IAZEFilter { fiSearch?: string; fiZeitraumVon?: string; fiZeitraumBis?: string; fiBuchungsart?: number[]; fiStatus?: number[]; }
- 过滤条件变更时触发更新
所有过滤输入控件的值变更时,把最新的IAZEFilter类型值做一次空值兜底后,序列化成字符串赋值给dataSource.filter,表格会自动完成过滤和重绘,不用手动操作原数据:
// 绑定到输入框、日期选择器、多选下拉的change/valueChanges事件 onFilterUpdate(latestFilter: IAZEFilter) { // 空值兜底,避免undefined字段导致判断异常 const safeFilter: IAZEFilter = { fiSearch: '', fiZeitraumVon: '', fiZeitraumBis: '', fiBuchungsart: [], fiStatus: [], ...latestFilter }; this.dataSource.filter = JSON.stringify(safeFilter); }
避坑提示:
- 时间判断必须统一转时间戳对比,不要直接用
dd.MM.yyyy这类本地化格式的字符串比大小,会出现逻辑错误- 数组类型的多选过滤条件必须先判断长度,空数组时跳过匹配,否则会出现无选中项时所有数据被过滤的问题
- 全局搜索记得统一转大小写后做匹配,避免大小写敏感导致漏匹配
- 以上方案仅适用于前端全量加载数据的场景,如果是服务端分页/过滤,直接把
IAZEFilter作为请求参数传给后端接口即可,不需要前端写过滤逻辑
内容的提问来源于stack exchange,提问作者Stef May
相关产品推荐
相关产品推荐

