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

如何在Angular 5的Mat Data Table中添加列筛选及自定义列筛选器

在Angular 5的Mat Data Table中实现列级筛选与自定义筛选器

我来帮你一步步搞定Angular 5里Mat Data Table的列级筛选和自定义筛选器,这是我平时项目里常用的方案,亲测有效:

一、基础列级筛选(文本/下拉框筛选)

Mat Data Table本身的MatTableDataSource提供了筛选能力,但默认是全局匹配,我们需要自定义filterPredicate来实现列级的精准筛选。

1. 准备组件与数据源

首先在你的组件里定义数据源和表格配置:

import { Component, OnInit } from '@angular/core';
import { MatTableDataSource } from '@angular/material';

// 定义你的数据接口
export interface User {
  id: string;
  name: string;
  email: string;
  role: string;
}

@Component({
  selector: 'app-user-table',
  templateUrl: './user-table.component.html',
  styleUrls: ['./user-table.component.css']
})
export class UserTableComponent implements OnInit {
  // 表格列定义
  displayedColumns: string[] = ['id', 'name', 'email', 'role'];
  dataSource: MatTableDataSource<User>;
  // 模拟数据
  userList: User[] = [
    { id: '1', name: 'John Doe', email: 'john@example.com', role: 'Admin' },
    { id: '2', name: 'Jane Smith', email: 'jane@example.com', role: 'User' },
    { id: '3', name: 'Bob Brown', email: 'bob@example.com', role: 'User' },
  ];

  ngOnInit() {
    this.dataSource = new MatTableDataSource(this.userList);
  }
}

2. 添加筛选控件到表格头部

在模板里给每个列的头部添加输入框或下拉框,并绑定筛选事件:

<table mat-table [dataSource]="dataSource" class="mat-elevation-z8">

  <!-- ID列 -->
  <ng-container matColumnDef="id">
    <th mat-header-cell *matHeaderCellDef>
      ID
      <input 
        matInput 
        (keyup)="applyColumnFilter('id', $event.target.value)" 
        placeholder="筛选ID"
      >
    </th>
    <td mat-cell *matCellDef="let user"> {{user.id}} </td>
  </ng-container>

  <!-- 姓名列 -->
  <ng-container matColumnDef="name">
    <th mat-header-cell *matHeaderCellDef>
      姓名
      <input 
        matInput 
        (keyup)="applyColumnFilter('name', $event.target.value)" 
        placeholder="筛选姓名"
      >
    </th>
    <td mat-cell *matCellDef="let user"> {{user.name}} </td>
  </ng-container>

  <!-- 邮箱列 -->
  <ng-container matColumnDef="email">
    <th mat-header-cell *matHeaderCellDef>
      邮箱
      <input 
        matInput 
        (keyup)="applyColumnFilter('email', $event.target.value)" 
        placeholder="筛选邮箱"
      >
    </th>
    <td mat-cell *matCellDef="let user"> {{user.email}} </td>
  </ng-container>

  <!-- 角色列(下拉框筛选) -->
  <ng-container matColumnDef="role">
    <th mat-header-cell *matHeaderCellDef>
      角色
      <mat-select 
        (selectionChange)="applyColumnFilter('role', $event.value)" 
        placeholder="筛选角色"
      >
        <mat-option value="">全部</mat-option>
        <mat-option value="Admin">管理员</mat-option>
        <mat-option value="User">普通用户</mat-option>
      </mat-select>
    </th>
    <td mat-cell *matCellDef="let user"> {{user.role}} </td>
  </ng-container>

  <tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
  <tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
</table>

3. 实现列级筛选逻辑

在组件里添加筛选方法,通过filterPredicate自定义匹配规则:

// 维护所有列的筛选条件
private filterConditions: {[key: string]: any} = {};

applyColumnFilter(column: string, value: string) {
  // 更新当前列的筛选条件
  this.filterConditions[column] = value.trim().toLowerCase();
  // 统一更新表格筛选
  this.updateTableFilter();
}

private updateTableFilter() {
  // 自定义筛选逻辑:检查每一列的筛选条件是否匹配
  this.dataSource.filterPredicate = (user: User, filterStr: string) => {
    const filters = JSON.parse(filterStr);
    for (const key in filters) {
      if (filters.hasOwnProperty(key)) {
        const filterValue = filters[key];
        // 如果筛选值为空,跳过该列检查
        if (!filterValue) continue;
        // 匹配当前列的值(忽略大小写)
        if (!user[key].toLowerCase().includes(filterValue)) {
          return false;
        }
      }
    }
    return true;
  };
  
  // 将筛选条件转为JSON字符串传递给数据源
  this.dataSource.filter = JSON.stringify(this.filterConditions);
}

这样每一列的筛选都独立生效,而且支持多列同时筛选。

二、自定义筛选器(比如日期范围、数值区间)

如果需要更复杂的筛选(比如日期范围),我们可以封装独立的筛选器组件,再和表格集成。

1. 创建自定义日期范围筛选器组件

import { Component, Output, EventEmitter } from '@angular/core';

@Component({
  selector: 'app-date-range-filter',
  template: `
    <mat-form-field style="margin-right: 10px; width: 160px;">
      <input 
        matInput 
        [matDatepicker]="startPicker" 
        placeholder="开始日期" 
        [(ngModel)]="startDate"
        (dateChange)="onFilterChange()"
      >
      <mat-datepicker-toggle matSuffix [for]="startPicker"></mat-datepicker-toggle>
      <mat-datepicker #startPicker></mat-datepicker>
    </mat-form-field>
    <mat-form-field style="margin-right: 10px; width: 160px;">
      <input 
        matInput 
        [matDatepicker]="endPicker" 
        placeholder="结束日期" 
        [(ngModel)]="endDate"
        (dateChange)="onFilterChange()"
      >
      <mat-datepicker-toggle matSuffix [for]="endPicker"></mat-datepicker-toggle>
      <mat-datepicker #endPicker></mat-datepicker>
    </mat-form-field>
    <button mat-button (click)="resetFilter()">重置</button>
  `
})
export class DateRangeFilterComponent {
  startDate: Date;
  endDate: Date;
  // 向外传递筛选条件
  @Output() filterChange = new EventEmitter<{start: Date, end: Date}>();

  onFilterChange() {
    this.filterChange.emit({ start: this.startDate, end: this.endDate });
  }

  resetFilter() {
    this.startDate = null;
    this.endDate = null;
    this.onFilterChange();
  }
}

2. 在表格组件中集成自定义筛选器

首先更新用户数据接口,添加joinDate字段:

export interface User {
  id: string;
  name: string;
  email: string;
  role: string;
  joinDate: Date;
}

更新表格列定义和模拟数据:

displayedColumns: string[] = ['id', 'name', 'email', 'role', 'joinDate'];
userList: User[] = [
  { id: '1', name: 'John Doe', email: 'john@example.com', role: 'Admin', joinDate: new Date(2022, 5, 10) },
  { id: '2', name: 'Jane Smith', email: 'jane@example.com', role: 'User', joinDate: new Date(2023, 1, 15) },
  { id: '3', name: 'Bob Brown', email: 'bob@example.com', role: 'User', joinDate: new Date(2021, 10, 20) },
];

添加处理日期筛选的方法:

applyDateRangeFilter(filter: {start: Date, end: Date}) {
  // 更新日期列的筛选条件
  this.filterConditions['joinDate'] = filter;
  // 统一更新表格筛选
  this.updateTableFilter();
}

// 重写updateTableFilter,加入日期筛选逻辑
private updateTableFilter() {
  this.dataSource.filterPredicate = (user: User, filterStr: string) => {
    const filters = JSON.parse(filterStr);
    for (const key in filters) {
      if (filters.hasOwnProperty(key)) {
        const filterValue = filters[key];
        if (!filterValue) continue;

        if (key === 'joinDate') {
          // 处理日期范围筛选
          const { start, end } = filterValue;
          const userJoinDate = new Date(user.joinDate);
          if (start && userJoinDate < new Date(start)) return false;
          if (end && userJoinDate > new Date(end)) return false;
        } else {
          // 处理文本类筛选
          if (!user[key].toLowerCase().includes(filterValue)) return false;
        }
      }
    }
    return true;
  };
  
  this.dataSource.filter = JSON.stringify(this.filterConditions);
}

最后在模板里添加日期列和自定义筛选器:

<ng-container matColumnDef="joinDate">
  <th mat-header-cell *matHeaderCellDef>
    入职日期
    <app-date-range-filter (filterChange)="applyDateRangeFilter($event)"></app-date-range-filter>
  </th>
  <td mat-cell *matCellDef="let user"> {{user.joinDate | date:'yyyy-MM-dd'}} </td>
</ng-container>

注意事项

  • 确保你的Angular Material版本和Angular 5兼容(推荐使用@angular/material 5.x版本)
  • 所有用到的Material组件(MatTable、MatInput、MatSelect、MatDatepicker等)都要在模块中正确导入
  • 如果需要更复杂的筛选逻辑,只需要扩展filterPredicate里的匹配规则即可

内容的提问来源于stack exchange,提问作者V L Sudhakar Inampudi

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.19 10:01:16