如何在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
相关产品推荐
相关产品推荐

