0

I'm using Angular 7 and Material 2, I have a mat-table with several columns and beneath the table I have a mat-slide-toggle.

When the mat-slide-toggle becomes checked, I want to filter one column (status) with an exact string match filter ('Active'). Then when the mat-slide-toggle is unchecked, I want to remove the filter from the column and display as normal.

I've looked at examples like custom filter in mat-table where they set a custom this.dataSource.filterPredicate which I've been able to do okay but I'm a bit stumped on:

  • When the mat-slide-toggle is unchecked, removing the filter.
  • When using the free-text filter option above the table (see code below), to use the default filter all columns.

I think for the second point I would need to reset this.dataSource.filterPredicate back to its default but I'm unsure of the code to do that.


Here are my code examples with unnecessary parts removed to keep them to the point. The status property only has two values 'Active' & 'Inactive', I want to filter only 'Active' users.

example.component.ts

export class UserComponent implements OnInit {
  users: User[] = [];
  displayedColumns: string[] = ['name', 'status'];
  dataSource = new MatTableDataSource(this.users);

  @ViewChild(MatPaginator) paginator: MatPaginator;
  @ViewChild(MatSort) sort: MatSort;

  constructor(private usersService: UsersService) { }

  ngOnInit() {
    this.getUsers();
    this.dataSource = new MatTableDataSource(this.users);
    this.dataSource.paginator = this.paginator;
    this.dataSource.sort = this.sort;
  }

  activeUserToggle(changeEvent: MatSlideToggleChange) {
    if (changeEvent.checked) {
      this.dataSource.filterPredicate =
        (user: User, filter: string) => user.status.indexOf(filter) != -1;
    } else {

    }
  }

  applyFilter(filterValue: string) {
    this.dataSource.filter = filterValue.trim().toLowerCase();

    if (this.dataSource.paginator) {
      this.dataSource.paginator.firstPage();
    }
  }
}

example.component.html

<mat-form-field>
    <input matInput (keyup)="applyFilter($event.target.value)" placeholder="Filter">
  </mat-form-field>

  <div class="mat-elevation-z8">
    <table mat-table [dataSource]="dataSource" matSort>

      <ng-container matColumnDef="name">
        <th mat-header-cell *matHeaderCellDef mat-sort-header> <b>Name</b> </th>
        <td mat-cell *matCellDef="let row"> {{row.name}} </td>
      </ng-container>

      <ng-container matColumnDef="status">
          <th mat-header-cell *matHeaderCellDef mat-sort-header> <b>Status</b> </th>
          <td mat-cell *matCellDef="let row"> {{row.status}} </td>
      </ng-container>

      <tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
      <tr mat-row *matRowDef="let row;
                              let even = even;
                              columns: displayedColumns;" [ngClass]="{grey: even}">
      </tr>
    </table>

    <mat-paginator [pageSizeOptions]="[10, 25, 100]"></mat-paginator>
  </div>

  <mat-slide-toggle class="activeUserSlide" (change)="activeUserToggle($event)">Show only active users</mat-slide-toggle>
Troy Poulter
  • 677
  • 1
  • 8
  • 29

1 Answers1

1

You can reset the values back to this.users when unchecked.

activeUserToggle(changeEvent: MatSlideToggleChange) {
    if (changeEvent.checked) {
      this.dataSource.filterPredicate =
        (user: User, filter: string) => user.status.indexOf(filter) != -1;
    } else {
      this.dataSource.data = this.users;
    }
  }
Akhi Akl
  • 3,795
  • 1
  • 15
  • 26
  • Is this the only way to do it? because I am getting the data from a service/ api call so I can't reassign the data source this way – SanDash Jul 13 '20 at 10:13
  • You mean you are filtering the data from api also? – Akhi Akl Jul 13 '20 at 15:38
  • When I am reassigning the datasource this way, the view not updating. I am having to do datasource = new MatTableDataSource(this.users); and also have to link the sorting and pagination again with datasource. – SanDash Jul 14 '20 at 12:35
  • I think to detect changes in the table that hast to be done. – Akhi Akl Jul 14 '20 at 13:40