Angular 5中Material DataTable多列自定义筛选需求及代码求助
Implement Multi-Column Filtering for Angular 5 Material DataTable
Got it, let's fix that multi-column filtering issue. The default global filter works great, but for per-column searches, we need to customize the filter logic and add individual inputs for each column. Here's how to do it:
Step 1: Update the Component (.ts)
First, we'll add a way to track filter values per column, then override the default filter predicate to check each column's filter against the corresponding data field.
import { HttpClient } from '@angular/common/http'; import { Component, OnInit, ViewChild, AfterViewInit } from '@angular/core'; import { MatTableDataSource, MatSort, MatPaginator } from '@angular/material'; // Assuming ELEMENT_DATA is your existing dataset (define it as needed) const ELEMENT_DATA = []; @Component({ selector: 'app-grid', templateUrl: './grid.component.html', styleUrls: ['./grid.component.scss'] }) export class GridComponent implements OnInit, AfterViewInit { grantsearch = []; @ViewChild(MatSort) sort: MatSort; @ViewChild(MatPaginator) paginator: MatPaginator; dataSource = new MatTableDataSource(ELEMENT_DATA); displayedColumns = ['number', 'title', 'agency', 'status', 'posted', 'closed']; // Object to store filter values for each column columnFilters: { [key: string]: string } = {}; constructor(private http: HttpClient) { } ngOnInit() { // Set up custom filter logic this.dataSource.filterPredicate = (data: any, filter: string) => { const filters = JSON.parse(filter); let isMatch = true; // Check each column's filter against the corresponding data property Object.keys(filters).forEach(column => { const filterValue = filters[column].trim().toLowerCase(); if (filterValue) { const dataValue = data[column] ? data[column].toString().toLowerCase() : ''; if (!dataValue.includes(filterValue)) { isMatch = false; } } }); return isMatch; }; } ngAfterViewInit() { this.dataSource.sort = this.sort; this.dataSource.paginator = this.paginator; } // Update filter for a specific column and trigger table filtering applyFilter(column: string, value: string) { this.columnFilters[column] = value; // Stringify the filters object to pass to the dataSource filter this.dataSource.filter = JSON.stringify(this.columnFilters); } }
Step 2: Update the Template (.html)
Replace the single global filter input with individual inputs for each column. We'll loop through your displayedColumns to create a filter input for every column:
<div class="example-container mat-elevation-z8"> <!-- Multi-column filter row --> <div class="example-header"> <div class="filter-row" style="display: flex; gap: 1rem; padding: 1rem;"> <mat-form-field *ngFor="let column of displayedColumns" style="width: 150px;"> <input matInput (keyup)="applyFilter(column, $event.target.value)" placeholder="Filter {{column}}" > </mat-form-field> </div> </div> <!-- Your complete table structure --> <table mat-table [dataSource]="dataSource" matSort> <!-- Number Column --> <ng-container matColumnDef="number"> <th mat-header-cell *matHeaderCellDef mat-sort-header> Number </th> <td mat-cell *matCellDef="let element"> {{element.number}} </td> </ng-container> <!-- Title Column --> <ng-container matColumnDef="title"> <th mat-header-cell *matHeaderCellDef mat-sort-header> Title </th> <td mat-cell *matCellDef="let element"> {{element.title}} </td> </ng-container> <!-- Agency Column --> <ng-container matColumnDef="agency"> <th mat-header-cell *matHeaderCellDef mat-sort-header> Agency </th> <td mat-cell *matCellDef="let element"> {{element.agency}} </td> </ng-container> <!-- Status Column --> <ng-container matColumnDef="status"> <th mat-header-cell *matHeaderCellDef mat-sort-header> Status </th> <td mat-cell *matCellDef="let element"> {{element.status}} </td> </ng-container> <!-- Posted Column --> <ng-container matColumnDef="posted"> <th mat-header-cell *matHeaderCellDef mat-sort-header> Posted </th> <td mat-cell *matCellDef="let element"> {{element.posted}} </td> </ng-container> <!-- Closed Column --> <ng-container matColumnDef="closed"> <th mat-header-cell *matHeaderCellDef mat-sort-header> Closed </th> <td mat-cell *matCellDef="let element"> {{element.closed}} </td> </ng-container> <tr mat-header-row *matHeaderRowDef="displayedColumns"></tr> <tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr> </table> <mat-paginator [pageSizeOptions]="[5, 10, 25]" showFirstLastButtons></mat-paginator> </div>
How It Works
- Column Filters Object: The
columnFiltersobject keeps track of the current search value for each column, using the column name as the key. - Custom Filter Predicate: We override
filterPredicateto parse the stringified filter object, then check each column's filter against the matching data property. Only rows that match all active filters are displayed. - Per-Column Inputs: Each input triggers
applyFilterwith its column name and value, updating the filter object and forcing the table to re-filter its rows.
Quick Notes
- Ensure your data objects have properties that exactly match the names in
displayedColumns(e.g.,element.numberexists ifnumberis in your column list). - Adjust the CSS (like input width and spacing in the filter row) to fit your layout requirements.
- Empty filter values are ignored, so leaving a column's input blank won't affect the filtering results.
内容的提问来源于stack exchange,提问作者Naeem Hussain
相关产品推荐
相关产品推荐

