Reputation: 1235
I created a page where I am showing angular material table data. On top of table data I put a filter input to show the data in filtered format. Things are working fine but i observed a strange and unexpected angular behavior. For some of characters, it is showing filtered rows on each key strokes, but for some other characters it does not show rows on keystrokes.
listusers.component.html
<div class="example-container mat-elevation-z8">
<mat-form-field>
<input matInput (keyup)="applyFilter($event.target.value)" placeholder="Filter" autocomplete="off">
</mat-form-field>
<table mat-table [dataSource]="dataSource">
<ng-container matColumnDef="position">
<th mat-header-cell *matHeaderCellDef> No. </th>
<td mat-cell *matCellDef="let element"> {{element.index}} </td>
</ng-container>
<ng-container matColumnDef="name">
<th mat-header-cell *matHeaderCellDef> Name </th>
<td mat-cell *matCellDef="let element"> {{element.name}} </td>
</ng-container>
<ng-container matColumnDef="gender">
<th mat-header-cell *matHeaderCellDef> Gender </th>
<td mat-cell *matCellDef="let element"> {{element.gender}} </td>
</ng-container>
<ng-container matColumnDef="score">
<th mat-header-cell *matHeaderCellDef> Score </th>
<td mat-cell *matCellDef="let element"> {{element.score}} </td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="displayedColumns; sticky: true"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns; let i = index"
></tr>
</table>
</div>
listusers.component.ts
import { Component, OnInit } from '@angular/core';
import { ListService } from '../services/list.service';
import { User } from '../model/user.model';
import { MatTableDataSource } from '@angular/material';
import { FormControl } from '@angular/forms';
@Component({
selector: 'listusers',
templateUrl: './listusers.component.html',
styleUrls: ['./listusers.component.css']
})
export class ListusersComponent implements OnInit {
public users: User[] = [];
displayedColumns = [ 'position','name', 'gender', 'score'];
dataSource: MatTableDataSource<User>;
constructor(private listsrv:ListService) { }
ngOnInit() {
this.loaddata();
if(this.dataSource){
this.dataSource.filterPredicate = (data: User, filtersJson: string) => {
const matchFilter = [];
const filters = JSON.parse(filtersJson);
filters.forEach(filter => {
const val = data[filter.id] == null ? '' : data[filter.id];
matchFilter.push(val.toLowerCase().includes(filter.value.toLowerCase()));
});
return matchFilter.every(Boolean);
};
}
}
applyFilter(filterValue: string) {
filterValue = filterValue.trim(); // Remove whitespace
filterValue = filterValue.toLowerCase(); // MatTableDataSource defaults to lowercase matches
this.dataSource.filter = filterValue;
console.log('filterValue',filterValue)
}
loaddata(){
this.listsrv.getList()
.subscribe(
result => {
for(var key in result){
this.users.push(result[key])
}
},
error => {console.log(' error',error)},
() => {console.log(this.users)
this.dataSource = new MatTableDataSource(this.users);
}
)
}
}
Some CSS is also there but not sharing as it to reduce the length of ques. The data which I am using is coming from a http service call
getList(){return this.http.get(this.url+'/list');}
Which is actually calling a route function on server and returns json object.
list.route.js
const express = require('express');
const router = express.Router();
router.get('/', function(req, res) {
var jsonobj = [
{name:"john",gender:"male", score:345,},
{name:"alice",gender:"female",score:678},
{name:"paul",gender:"male",score:263},
{name:"tia",gender:"female",score:620},
{name:"michel",gender:"male",score:458},
{name:"akbar",gender:"male",score:382},
{name:"simon",gender:"male",score:193},
{name:"albela",gender:"male",score:193}
]
console.log('list route called')
res.send(jsonobj)
})
module.exports = router;
I tried to make project in stackblitz.com and plunker but couldn't replicate issue for some setup related problems. I observed the when i press other keys like "t","j","u" etc. then it works but when i press "a" it does not show "alice" and "albela" rows. i have to keep entering and it shows rows when 3 characters are typed.
It is also not showing any error on console so i have no clue. Please have a look and suggest me.
Thanks
Upvotes: 1
Views: 5838
Reputation: 1235
I found the solution here
this.dataSource.filterPredicate was not configured properly and also at wrong place. My modified listusers.component.ts is as below,
listusers.component.ts
import { Component, OnInit } from '@angular/core';
import { ListService } from '../services/list.service';
import { User } from '../model/user.model';
import { MatTableDataSource } from '@angular/material';
import { FormControl } from '@angular/forms';
@Component({
selector: 'listusers',
templateUrl: './listusers.component.html',
styleUrls: ['./listusers.component.css']
})
export class ListusersComponent implements OnInit {
public users;
displayedColumns = [ 'position','name', 'gender', 'score'];
dataSource: MatTableDataSource<User>;
constructor(private listsrv:ListService) { }
ngOnInit() {
this.loaddata();
}
applyFilter(filterValue: string) {
this.dataSource.filter = filterValue.trim().toLowerCase();
}
loaddata(){
console.log('in function loaddata')
this.listsrv.getList()
.subscribe(result =>
this.users = result,
error => console.log('Error :',error),
() => { console.log(this.users);
this.dataSource = new MatTableDataSource(this.users);
//added below line
this.dataSource.filterPredicate =
(data: User, filter: string) => data.name.indexOf(filter) != -1;
})
}
}
Upvotes: 3