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

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 columnFilters object keeps track of the current search value for each column, using the column name as the key.
  • Custom Filter Predicate: We override filterPredicate to 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 applyFilter with 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.number exists if number is 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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 04:20:52