简体   繁体   中英

angular 7 material table - filter is not working properly

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

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;
                })
  }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM