角材料:垫台多列动态数据过滤器

时间:2020-07-29 17:05:45

标签: angular typescript angular-material mat-table

我正在使用Angular材质表,显示从后端获取的动态数据。单列搜索效果很好。现在,我想实现多列搜索。谁能帮我实现这个目标吗?

HTML

<div >
  <ng-container *ngIf="columns && columns.length">
    <table mat-table matTableExporter [dataSource]="dataSource" #exporter="matTableExporter">
      <!-- actions -->
      <ng-container matColumnDef="actions">

        <th mat-header-cell *matHeaderCellDef>
          Update
          </th>

        <td class="trendCol icons" mat-cell *matCellDef="let element;">
          <button mat-icon-button  style="margin:5px;" color="accent" (click)="navigateToTrendEdit(element.unique_id)">
            <mat-icon aria-label="Edit">edit</mat-icon>
          </button>

          <button mat-icon-button style="margin:5px;" color="accent" (click)="deleteItem(element.unique_id)">
            <mat-icon aria-label="Delete">delete</mat-icon>
          </button>
        </td>
      </ng-container>
      <ng-container *ngFor="let column of columns; let i = index" [matColumnDef]="column.columnDef">
        <th mat-header-cell *matHeaderCellDef>
          {{ column.header }}
          <mat-icon class="filter_icon" (click)="openFilterDynamic(i)"
            >filter_alt</mat-icon
          ><br>
          <div *ngIf="openId === i">
            <mat-form-field>
              <input
                matInput
                type="text" [(ngModel)]="searchValue"
                class="form-field"
                (ngModelChange)="onSearchChange(column.columnDef)"
              />
              <button mat-button *ngIf="searchValue" matSuffix mat-icon-button aria-label="Clear" (click)="closeSearch(column.columnDef)">
                <mat-icon>close</mat-icon>
              </button>
            </mat-form-field>
          </div>
        </th>
        <td class="trendCol" mat-cell *matCellDef="let row">
          <div class="tooltip">
            <span class="userRecord">{{ column.cell(row) }}</span>
            <span class="tooltiptext">{{ column.cell(row) }}</span>
          </div>
        </td>
      </ng-container>
      <tr mat-header-row *matHeaderRowDef="dynamicColumns"></tr>
      <tr mat-row *matRowDef="let row; columns: dynamicColumns"></tr>
    </table>
    <mat-paginator
    [pageSize]="6"
    [pageSizeOptions]="[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 20]"
    showFirstLastButtons
    >
    </mat-paginator>
    <div class="downloadDiv">
      Download as :
      <button style="margin:5px;" mat-raised-button (click)="exporter.exportTable('xlsx')">Excel</button>
      <button style="margin:5px;" mat-raised-button (click)="exporter.exportTable('csv')">Csv</button>
      <button style="margin:5px;" mat-raised-button (click)="exporter.exportTable('json')">Json</button>
      <button style="margin:5px;" mat-raised-button (click)="exporter.exportTable('txt')">Txt</button>
    </div>
  </ng-container>
</div>

TS

import { Component, OnInit, ViewChild, AfterViewInit } from '@angular/core';
import { MatTableDataSource } from '@angular/material/table';
import { MatPaginator } from '@angular/material/paginator';
import {MatDialog} from '@angular/material/dialog';
import { Router } from '@angular/router';
import {BehaviorSubject} from 'rxjs';

@Component({
  selector: 'app-trends-list',
  templateUrl: './trends-list.component.html',
  styleUrls: ['./trends-list.component.scss'],
})
export class TrendsListComponent implements OnInit, AfterViewInit {
  
  index: number;
  id: string;

  dataChange: BehaviorSubject<TrendsForView[]> = new BehaviorSubject<TrendsForView[]>([]);
  
  public dataSource = new MatTableDataSource<TrendsForView>();

  globalFilter = '';

  @ViewChild(MatPaginator, {static: false})
  set paginator(value: MatPaginator) {
    this.dataSource.paginator = value;
  }
  
  columns: Array < {
    columnDef: string;
    header: string;
    cell: (element: any) => any;
  } > = [];
  dynamicColumns = ['actions', ...this.columns.map(c => c.columnDef)];
  searchValue = '';
  openId: number;
  constructor(private router: Router, private _router: Router,private trendsService: TrendsService, public dialog: MatDialog) {}

  ngOnInit(): void {
    this.getAllTrends();
    this.dataSource.filterPredicate = this.customFilterPredicate();
  }

  onSearchChange(key: string) {
    this.dataSource.filter = JSON.stringify({key, value: this.searchValue.toLowerCase()});
  }
  closeSearch(key: string) {
    this.searchValue = '';
    this.dataSource.filter = JSON.stringify({key, value: this.searchValue.toLowerCase()});
  }

  customFilterPredicate() {
    const myFilterPredicate = (
      data: TrendsForView,
      filter: string
    ): boolean => {
      let searchString = JSON.parse(filter);
      if (this.searchValue) {
        return data[searchString.key].toString().trim().toLowerCase().indexOf(searchString.value) !== -1;
      } else {
        return true;
      }
     
    }
    return myFilterPredicate;
  }
  ngAfterViewInit(): void {
    this.dataSource.paginator = this.paginator;
  }
  public getTrends = () =>{
    this.trendsService.getTrend().subscribe((res) => {
      this.dataSource.data = res.all_docs;
    });
  };
  public getAllTrends = () => {
    this.trendsService.getTrend().subscribe((res) => {
      this.dataSource.data = res.all_docs;
      const columns = this.dataSource.data[0];
            if (columns) {
        Object.keys(columns).forEach((key) => {
          if(key!="unique_id"){
            this.columns.push({
              header: key.replace(/_/g, ' '),
              columnDef: key,
              cell: (element: any) => element[key]
            });
          }
        });
        this.dynamicColumns = ['actions', ...this.columns.map(c => c.columnDef)];
      }
    });
  };
  openFilterDynamic(index: number) {
    this.openId = (this.openId === index) ? undefined : index;
    this.closeSearch('')
  }

  public redirectToDetails = (id: string) => {
    this.router.navigate(['/home']);
  };

  navigateToTrendEdit(id: any){
    this._router.navigateByUrl('/home' + id);
  }

  deleteItem(id: any){
    this.openDialog(id);
  }

  openDialog(id: any) {
    const dialogRef = this.dialog.open(DeleteTrendDialogComponent,{
      data: {
        message: id
      }
    });

    dialogRef.afterClosed()
          .subscribe(result => {
            if (result === 'closed') {
              this.getTrends();
         }
          });


  }
}

正如我所说的,单列搜索可以很好地工作,但是我对如何进行多列搜索感到困惑。

1 个答案:

答案 0 :(得分:0)

您尝试过mat-table-filter软件包吗?

作为示例,您需要有一个示例实体来代表您的过滤对象,当您填充其属性时,表格会自动被过滤。

<table mat-table matTableFilter [dataSource]="dataSource" [exampleEntity]="exampleObject"...>