【发布时间】:2020-11-19 08:28:27
【问题描述】:
我正在使用 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();
}
});
}
}
正如我所说的单列搜索工作正常,但我被困在如何进行多列搜索。
【问题讨论】:
-
默认情况下,角度材质会对多列进行过滤。 github.com/angular/components/blob/master/src/material/table/… 它将行中的所有值组合成一个字符串,然后尝试匹配您的过滤器字符串。
-
是的,但是我的要求有点不同,我对每一列都有单独的搜索字段。如果我搜索一列并过滤数据并尝试从另一列搜索,则应从先前过滤的数据中过滤数据
-
您可以存储最后的过滤器字符串并将其与新的过滤器字符串组合并传递给数据源的filterPredicate。
-
你找到答案了吗
标签: angular typescript angular-material mat-table