Angular自定义数据源表格过滤失效,求转用MatTableDataSource方案
我来帮你解决这两个问题——先修复现有自定义过滤的失效问题,再教你平滑切换到MatTableDataSource,完全不会破坏现有模块。
一、修复现有自定义过滤方法
你的过滤失效核心原因是:当前代码没有把过滤条件加入数据流的触发逻辑里,而且直接操作dataSource.data['title'].filter的方式是错误的。我们需要把过滤变化转换成可观察流,和分页、排序一起参与数据计算:
1. 修改op-dta-datasource.ts,添加过滤流和逻辑
import { DataSource, Observable, merge, observableOf } from 'rxjs'; import { map } from 'rxjs/operators'; import { MatPaginator, MatSort } from '@angular/material'; import { Subject } from 'rxjs'; // 新增导入 export interface OpDataSecondItem { id: number; title:string; close_date:Date; } export class OpDataSecondDataSource extends DataSource<OpDataSecondItem> { data: OpDataSecondItem[]; paginator: MatPaginator; sort: MatSort; // 新增过滤主题,用于触发过滤变化 private filterSubject = new Subject<string>(); public filter$ = this.filterSubject.asObservable(); constructor() { super(); } // 新增设置过滤的公共方法 setFilter(filterValue: string) { this.filterSubject.next(filterValue); } connect(): Observable<OpDataSecondItem[]> { // 将过滤流加入数据变更的触发源 const dataMutations = [ observableOf(this.data), this.paginator.page, this.sort.sortChange, this.filter$ ]; return merge(...dataMutations).pipe(map(() => { // 顺序:先过滤 → 再排序 → 最后分页 const filteredData = this.getFilteredData([...this.data]); const sortedData = this.getSortedData(filteredData); return this.getPagedData(sortedData); })); } // 新增过滤逻辑方法 private getFilteredData(data: OpDataSecondItem[]): OpDataSecondItem[] { const filterValue = this.filterSubject.value; if (!filterValue) return data; const lowerCaseFilter = filterValue.trim().toLowerCase(); // 可根据需要扩展过滤字段(比如id、close_date等) return data.filter(item => item.title.toLowerCase().includes(lowerCaseFilter) || item.id.toString().includes(lowerCaseFilter) || item.close_date.toLocaleDateString().toLowerCase().includes(lowerCaseFilter) ); } // 保留你原有的getSortedData方法 private getSortedData(data: OpDataSecondItem[]): OpDataSecondItem[] { // 你的原有排序逻辑代码 } // 保留你原有的getPagedData方法 private getPagedData(data: OpDataSecondItem[]): OpDataSecondItem[] { // 你的原有分页逻辑代码 } disconnect() {} }
2. 修改组件内的过滤方法
在op-dta.component.ts里,把applyFilter和onSearchClear改成调用数据源的过滤方法:
applyFilter() { this.dataSource.setFilter(this.searchKey.trim().toLowerCase()); } onSearchClear() { this.searchKey = ""; this.applyFilter(); }
这样修改后,你的自定义过滤就能正常触发,并且和分页、排序联动了。
二、平滑切换到MatTableDataSource(无模块破坏)
MatTableDataSource是Angular Material官方封装的数据源,已经内置了分页、排序、过滤逻辑,切换起来非常简单,完全不需要修改模板和服务调用:
1. 修改组件内的数据源类型和逻辑
import { MatTableDataSource } from '@angular/material/table'; // 新增导入 @Component({ selector: 'op-data-second', templateUrl: './op-data-second.component.html', styleUrls: ['./op-data-second.component.css'] }) export class OpDataSecondComponent implements AfterViewInit, OnInit { @ViewChild(MatPaginator) paginator: MatPaginator; @ViewChild(MatSort) sort: MatSort; @ViewChild(MatTable) table: MatTable<OpDataSecondItem>; // 替换原有数据源类型为MatTableDataSource dataSource: MatTableDataSource<OpDataSecondItem>; searchKey: string; displayedColumns = ['id', 'title','close_date','published_date']; constructor(private service: HttpserviceService){} ngOnInit() { // 初始化MatTableDataSource this.dataSource = new MatTableDataSource<OpDataSecondItem>(); this.service.getOps('').subscribe((data:OpDataSecondItem[])=>{ // 直接赋值数据即可 this.dataSource.data = data; }); } ngAfterViewInit() { // 绑定分页和排序 this.dataSource.paginator = this.paginator; this.dataSource.sort = this.sort; this.table.dataSource = this.dataSource; } onSearchClear() { this.searchKey = ""; this.applyFilter(); } // 简化过滤方法,直接使用MatTableDataSource的内置过滤 applyFilter() { this.dataSource.filter = this.searchKey.trim().toLowerCase(); // 如果你需要自定义过滤规则(比如只匹配指定字段),可以添加这段: // this.dataSource.filterPredicate = (data: OpDataSecondItem, filter: string) => { // return data.title.toLowerCase().includes(filter) || // data.id.toString().includes(filter) || // data.close_date.toLocaleDateString().toLowerCase().includes(filter); // }; } }
2. 清理冗余代码
切换完成后,你可以直接删除原来的op-dta-datasource.ts文件,因为MatTableDataSource已经完全替代了它的功能,而且你的模板不需要做任何修改——分页器、排序、表格的绑定逻辑和原来完全一致,不会破坏现有模块。
两种方案任选其一即可:如果想保留自定义数据源的灵活性,就用第一种修复方案;如果想简化代码、使用官方推荐的实现,第二种切换方案会更省心。
内容的提问来源于stack exchange,提问作者Talib Daryabi
相关产品推荐
相关产品推荐

