This is a late answer but surely will help for those who are interested.
You can use mat-table-filter for filtering. It supports array filtering too. It saves you from implementing filtering boilerplate including debounce etc.
The only thing you need to do is adding matTableFilter
directive to your material table and binding exampleEntity
with a representation of what you have as an item inside your datasource.
<table mat-table matTableFilter [dataSource]="dataSource"
[exampleEntity]="exampleObject"...>
That's all. When you populate the exampleObject's properties, the filter will automatically work just fine with the default debounce support. You can change the debounce time also.
You can take a look at the examples here: https://halittalha.github.io/ng-material-extensions/
I'm sharing the full array filtering source code below.
The below example leverages chips component to collect the array contents for filtering.
.html
<mat-table matTableFilter [exampleEntity]="filterEntity" [filterType]="filterType" [dataSource]="dataSource"
class="mat-elevation-z8">
<ng-container matColumnDef="category">
<mat-header-cell *matHeaderCellDef>
<mat-form-field appearance="outline">
<input matInput placeholder="Category" [(ngModel)]="filterEntity.category">
</mat-form-field>
</mat-header-cell>
<mat-cell *matCellDef="let element"> {{element.category}} </mat-cell>
</ng-container>
<ng-container matColumnDef="brand">
<mat-header-cell *matHeaderCellDef>
<mat-form-field appearance="outline">
<input matInput placeholder="Product Brand" [(ngModel)]="filterEntity.brand">
</mat-form-field>
</mat-header-cell>
<mat-cell *matCellDef="let element"> {{element.brand}} </mat-cell>
</ng-container>
<ng-container matColumnDef="availableSizes">
<mat-header-cell *matHeaderCellDef>
<mat-form-field class="example-chip-list">
<mat-chip-list #chipList aria-label="Fruit selection">
<mat-chip *ngFor="let size of filterEntity.availableSizes" [selectable]="true" [removable]="true"
(removed)="remove(size)">
{{size}}
<mat-icon matChipRemove>cancel</mat-icon>
</mat-chip>
<input placeholder="Add Size" [matChipInputFor]="chipList"
[matChipInputSeparatorKeyCodes]="separatorKeysCodes" [matChipInputAddOnBlur]="true"
(matChipInputTokenEnd)="add($event)">
</mat-chip-list>
</mat-form-field>
</mat-header-cell>
<mat-cell *matCellDef="let element"> {{element.availableSizes}} </mat-cell>
</ng-container>
<mat-header-row *matHeaderRowDef="displayedColumns"></mat-header-row>
<mat-row *matRowDef="let row; columns: displayedColumns;"></mat-row>
</mat-table>
.ts
import { MatTableFilter } from 'mat-table-filter';
import { Component, OnInit } from '@angular/core';
import { MatTableDataSource, MatChipInputEvent } from '@angular/material';
import { COMMA, ENTER } from '@angular/cdk/keycodes';
export class Product {
category: string;
brand: string;
availableSizes: Array<string>;
}
const PRODUCTS: Product[] = [
{category: 'T-Shirt', brand: 'X', availableSizes: ['S', 'M', 'L', 'XL']},
{category: 'T-Shirt', brand: 'Y', availableSizes: ['S', 'L', 'XL']},
{category: 'T-Shirt', brand: 'Z', availableSizes: ['XL']},
{category: 'Jean', brand: 'X', availableSizes: ['S', 'M', 'L', 'XL']},
{category: 'Jean', brand: 'Y', availableSizes: ['S', 'M']},
{category: 'Jean', brand: 'Z', availableSizes: ['S', 'M', 'L']},
{category: 'Jean', brand: 'B', availableSizes: ['S', 'M', 'L']},
{category: 'Jacket', brand: 'X', availableSizes: ['S', 'L', 'XL']},
{category: 'Jacket', brand: 'Z', availableSizes: ['S']},
{category: 'Pants', brand: 'X', availableSizes: ['S', 'M', 'L', 'XL']},
{category: 'Pants', brand: 'Y', availableSizes: ['L', 'XL']},
{category: 'Pants', brand: 'Z', availableSizes: ['S']},
{category: 'Hat', brand: 'X', availableSizes: ['S', 'M', 'L']},
{category: 'Skirt', brand: 'X', availableSizes: ['S', 'M', 'L', 'XL']},
{category: 'Skirt', brand: 'Y', availableSizes: ['S', 'M', 'L']}
];
@Component({
selector: 'app-array-filter',
templateUrl: './array-filter.component.html',
styleUrls: ['./array-filter.component.css']
})
export class ArrayFilterComponent implements OnInit {
filterEntity: Product;
filterType: MatTableFilter;
displayedColumns: string[] = ['category', 'brand', 'availableSizes'];
dataSource;
readonly separatorKeysCodes: number[] = [ENTER, COMMA];
add(event: MatChipInputEvent): void {
const input = event.input;
const value = event.value;
if ((value || '').trim()) {
this.filterEntity.availableSizes.push(value.trim());
}
// Reset the input value
if (input) {
input.value = '';
}
}
remove(size: string): void {
const index = this.filterEntity.availableSizes.indexOf(size);
if (index >= 0) {
this.filterEntity.availableSizes.splice(index, 1);
}
}
ngOnInit() {
this.filterEntity = new Product();
this.filterEntity.availableSizes = new Array<string>(); // DO NOT FORGET TO INIT THE ARRAY
this.filterType = MatTableFilter.ANYWHERE;
this.dataSource = new MatTableDataSource(PRODUCTS);
}
}