Home > Software engineering >  angular MatTableDataSource filterPredicate does not update the table after filter updates
angular MatTableDataSource filterPredicate does not update the table after filter updates

Time:10-22

import { Component, OnInit, AfterViewInit } from '@angular/core';
import { Coach } from "../../shared/models/User";
import { ManagementService } from "../../shared/services/management.service";
import { Router } from '@angular/router';
import { UtilsService } from 'src/app/shared/services/utils.service';
import * as moment from 'moment';
import swal from 'sweetalert2';
import { FormControl } from '@angular/forms';
import { MatTableDataSource } from '@angular/material/table';

@Component({
    selector: 'app-coaches',
    templateUrl: './coaches.component.html',
    styleUrls: ['./coaches.component.css']
})
export class CoachesComponent implements OnInit, AfterViewInit {
    dataSource;
    columnsToDisplay = ['username', 'email', 'actions'];
    coachList: Array<Coach> = [];
    username
    usernameFilter = new FormControl('');

    constructor(
        private managementService: ManagementService,
        private router: Router,
        private utils: UtilsService
    ) {
        this.dataSource = new MatTableDataSource();
        this.dataSource.filterPredicate = this.createFilter();
    }
    async ngAfterViewInit() {
        // await this.initializePage();
    }

    ngOnInit() {
        this.initializePage();

        this.usernameFilter.valueChanges
            .subscribe(
                username => {
                    this.username = username;
                    this.dataSource.filter = this.username;
                    console.log(this.dataSource.filter)
                }
            )
    }

    createFilter(): (data: Coach, filter: string) => boolean {
        let filterFunction = function (data, filter): boolean {
            return data.username.toLowerCase().indexOf(filter.toLowerCase()) !== -1
        }
        return filterFunction;
    }

    async initializePage() {
        let coaches: Array<Coach> = await this.managementService.getCoaches();
        this.coachList = coaches.sort(
            (prev, next) => {
                return moment(prev.createdAt).isBefore(moment(next.createdAt)) ? 1 : -1;
            }
        );
        this.dataSource = this.coachList
    }
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.7.5/angular.min.js"></script>
<div >
  <div >
    <div >
      <div >
        <div >
          <div >
            <div >
              <i >account_circle</i>
            </div>
            <h4 >Coaches</h4>
          </div>
          <div >
            <div >
              <button mat-raised-button  (click)="registerCoach()">Register</button>
              <div  style="float: right;">
                <mat-form-field appearance="standard">
                  <mat-label>Filter</mat-label>
                  <input matInput [formControl]="usernameFilter" placeholder="username" #input>
                </mat-form-field>
              </div>
            </div>
            <div style="text-align: center" *ngIf="coachList.length === 0">
              <br>
              <div style="font-style: italic; color: gray">.:: No Registered Coaches ::.</div>
            </div>
            <table mat-table [dataSource]="dataSource" 
              cellspacing="0" width="100%" style="width:100%">
              <ng-container matColumnDef="username">
                <th mat-header-cell *matHeaderCellDef> Username </th>
                <td mat-cell *matCellDef="let row"> {{row.username}} </td>
              </ng-container>
              <ng-container matColumnDef="email">
                <th mat-header-cell *matHeaderCellDef> Email </th>
                <td mat-cell *matCellDef="let row"> {{row.email}} </td>
              </ng-container>
              <ng-container matColumnDef="actions">
                <th mat-header-cell *matHeaderCellDef> Actions </th>
                <td mat-cell *matCellDef="let row">
                  <app-button-delete (onClick)="deleteCoach(coach.id)"></app-button-delete>
                </td>
              </ng-container>
              <tr mat-header-row *matHeaderRowDef="columnsToDisplay"></tr>
              <tr mat-row *matRowDef="let row; columns: columnsToDisplay;"></tr>
            </table>
            <mat-paginator showFirstLastButtons [pageSizeOptions]="[10, 25, 50, 100]"></mat-paginator>
          </div>
        </div>
      </div>
    </div>
  </div>
</div>

I am very new to Angular and I am working on a project previously owned by other people.

The question goes as the title, I have done a lot of search around but none of the answers from stackoverflow works for me so far.

Below are the code, let me know if you need other information.

enter image description here

enter image description here

enter image description here

in a word, for some reason the filter function does not update the table content, which is confusing because it seems that the filter function works from another component, with essentially the same code.

This really confused me. Thank you in advance for any help and suggestion!!!

CodePudding user response:

You need to assign coachList as data of the dataSource.

// replace this line
 this.dataSource = this.coachList

// with this
 this.dataSource.data = this.coachList

when you create the dataSourse as an instance of MatTableDataSource the data array that is displayed is stored in the data property of the data source object, you can read more about MatTableDataSource here

  • Related