Yuuya
Yuuya

Reputation: 107

angular MatTableDataSource filterPredicate does not update the table after filter updates

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 class="main-content zero_margin">
  <div class="container-fluid">
    <div class="row">
      <div class="col-md-12">
        <div class="card">
          <div class="card-header card-header-primary card-header-icon">
            <div class="card-icon">
              <i class="material-icons">account_circle</i>
            </div>
            <h4 class="card-title">Coaches</h4>
          </div>
          <div class="card-body">
            <div class="toolbar">
              <button mat-raised-button class="btn btn-primary" (click)="registerCoach()">Register</button>
              <div class="col-lg-3 col-md-6 col-sm-4 add-select" 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" class="table table-striped table-no-bordered table-hover"
              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!!!

Upvotes: 0

Views: 1002

Answers (1)

Mr. Stash
Mr. Stash

Reputation: 3140

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

Upvotes: 2

Related Questions