I want to create generic table that takes tableColumns and dataSource as @Input(). I would like to be able to add custom fitlering by each table column. For the moment I have managed to initialize table FormGroup and to get FormGroup value on which I want to filter but further from here I really don't know how to proceede. I have tried to implement pipe and look at the other simillar solutions on internet but they all assume I know what are my tableColums (that I don't know as I am creating them dynamically.
Here is my code
<table mat-table [dataSource]="dataSource">
<ng-container *ngFor="let col of tableColumns; let i = index" [matColumnDef]="col.key">
<ng-container>
<th class="header" mat-header-cell *matHeaderCellDef>
<span *ngIf="!col.config">
{{ col['display'] }}
</span>
<form [formGroup]="form">
<mat-form-field *ngIf="!col.config" class="filter">
<input matInput placeholder="Filter" formControlName="{{tableColumns[i].key}}">
</mat-form-field>
</form>
</th>
<td mat-cell *matCellDef="let element; let row">
<ng-container>
{{ element[col.key] }}
</ng-container>
</td>
</ng-container>
</ng-container>
<tr mat-header-row *matHeaderRowDef="keys"></tr>
<tr mat-row *matRowDef="let row; columns: keys"></tr>
</table>
and then in my ts file I have following:
@Input() tableColumns: GenericTableColumn[] = []
@Input() dataSource: Array<object> = []
ngOnInit(): void {
this.initFormControls()
this.registerFormChangeListener()
}
initFormControls() {
const formGroup: FormGroup = new FormGroup({})
this.tableColumns.forEach((column) => {
if (column.key !== 'actions') {
let control: FormControl = new FormControl('')
formGroup.addControl(column.key, control)
}
})
this.form = formGroup
}
my idea was to create another function that will transform my input of dataSource into MatTableDataSource and apply custom filter predicate. Something like this:
registerFormChangeListener(){
const tableDataSource = new MatTableDataSource(this.dataSource)
tableDataSource.filterPredicate((tableDataSource, filter) => {
// here I need to filter by object key value
})
}
my dataSource = {
{
"id": "1",
"name": "someValue1",
"someOtherKey": "someOtherValue"
},
{
"id": "2",
"name": "someValue2",
"someOtherKey": "someOtherValue2"
},
{
"id": "3",
"name": "someValue3",
"someOtherKey": "someOtherValue2"
}
}
my filter object that is actually value of my form is:
{
"id": "",
"name": "someValue1",
"someOtherKey": "someOtherValue2"
}
and I am hoping to get my result as:
const fitleredResults = [
{
"id": "1",
"name": "someValue1",
"someOtherKey": "someOtherValue"
},
{
"id": "2",
"name": "someValue2",
"someOtherKey": "someOtherValue2"
}
]
Thanks for your help!
You need understand how a customFilter function work
filterthat it's a stringWhen we have severals field to filter you can use JSON.stringify to generate the "string" and JSON.parse to recover the object
Perhafs this SO can sirve as inspiration
Tip: To iterate over all the keys of one object use Object.Keys or Object.Entries
Update
Well the customFilter is a bit complex
We use reduce. reduce it's only a way to loop thought of elements of one array and return an unique result. you can see as a simple loop like this
To the last part, the custom filter I wrote a stackblitz to see how works
NOTE: perhafs you need check againts toUpperCase()