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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.11 08:31:11