Sorting and filtering utils to create generic Angular Material tables
A small set of utils to make Angular Material Tables more generic.
- Sorting based on column names, with nested property support using dot notation
- Filtering based on column names, with nested property support using dot notation
- Sorts string values case-insensitive
- Filter only on displayed columns (case-insensitive and trimming the filter string)
- Persisted sorting using SessionStorage
- Reactive data source for RxJS Observables
- Reloading functionality (for reactive data sources)
When using Angular Material Table, you may need more advanced sorting and filtering behaviour. That's why you usually end up with a lot of boilerplate code.
This library provides some utils to use consistent sorting and filtering behaviour for all your tables.
npm install @dirkluijk/ngx-generic-material-tables --save-dev
yarn add @dirkluijk/ngx-generic-material-tables --dev
The GenericTableDataSource
allows you to use "dot notation" for your columns and benefit from the following features:
- Only filter on the displayed columns (which you need to pass to it), using the dot notation
- Use the sortable columns based on the values accessed using the dot notation
import { Component } from '@angular/core';
import { GenericTableDataSource } from '@dirkluijk/ngx-generic-material-tables'
@Component({
template: `
<table mat-table [dataSource]="genericDataSource" matSort gmtApplyMatSort>
<ng-container matColumnDef="name">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Name</th>
<td mat-cell *matCellDef="let row">
{{ row.name }}
</td>
</ng-container>
<ng-container matColumnDef="foo.bar">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Foo Bar</th>
<td mat-cell *matCellDef="let row">
{{ row.foo.bar }}
</td>>
</ng-container>
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns"></tr>
</table>
`
})
export class MyComponent {
public displayedColumns = ['name', 'foo.bar'];
public genericDataSource = new GenericTableDataSource<YourRecordEntity>(this.displayedColumns, [/** your data */]);
}
Use the gmtApplyMatSort
to automatically register the MatSort
on the data source.
<table mat-table [dataSource]="genericDataSource" matSort gmtApplyMatSort>
<!-- ... -->
</table>
This allows you to leave out the following code:
ViewChild(MatSort, {static: true}) sort: MatSort; // not needed anymore!
ngOnInit(): void {
this.dataSource.sort = this.sort; // not needed anymore!
}
You can persist the sorting actions to SessionStorage using the gmtPersistedSort
directive.
Just pass an additional identifier for your table in order to distinguish between multiple tables.
<table mat-table [dataSource]="genericDataSource" matSort gmtPersistedSort="my-table">
<!-- ... -->
</table>
That's it!
Even more awesome is the reactive version of the GenericTableDataSource
:
- Pass the displayed columns, table data and filter data as
Observable
stream - Automatically reacts to changes
- Provides
reload()
functionality - Provides
loading
/success
/failed
static properties - Provides
loading$
/success$
/failed$
Observable properties
import { ReactiveGenericTableDataSource } from '@dirkluijk/ngx-generic-material-tables'
const dataSource = new ReactiveGenericTableDataSource<YourRecordEntity>(
displayedColumns$,
yourTableData$,
yourFilter$ // (optional)
);
dataSource.reload();
If you still want to have custom filtering for a specific column, filter value or column value,
you can pass a ColumnFilterPredicate
:
import { defaultColumnFilterPredicate } from '@dirkluijk/ngx-generic-material-tables';
dataSource.columnFilterPredicate = (value, filter, columnName) => {
// exact filter for this column
if (columnName === 'vehicle.number') {
return value.trim().includes(filter);
}
// custom filter for number values
if (typeof value === 'number') {
return String(yourFormatFn(value)).includes(filter);
}
return defaultColumnFilterPredicate(value, filter, columnName); // use default predicate for other cases
};
Thanks goes to these wonderful people (emoji key):
Dirk Luijk π» π |
This project follows the all-contributors specification. Contributions of any kind welcome!