Mat-Table Selection only on current PageSize?

My solution is based on currently displayed rows so it works regarding the pagination. There is a lot to improve about it so please feel free to make it better.

  isAllSelected() {

    const numSelected = this.selection.selected.length;
    const displayedRows = this.filteredEvents.connect().value.length;
    let isAllSelected = (numSelected === displayedRows);

    if (isAllSelected) {
      isAllSelected = this.isAllDisplayedSelected();
    }

    return isAllSelected;
  }

  isAllDisplayedSelected() {
    let isAllDisplayedSelected = true;

    if (this.selection.selected.length === 0) {
      return this.isAllSelected();
    }

    this.filteredEvents.connect().value.some(element => {
      if (!this.selection.isSelected(element)) {
        isAllDisplayedSelected = false;
        return isAllDisplayedSelected;
      }
    });
    return isAllDisplayedSelected;
  }

  masterToggle() {
    this.isViewableSelected() ?
      this.deselectRows() :
      this.selectRows();
  }

  isViewableSelected() {
    return (this.isAllSelected() || this.isAllDisplayedSelected());
  }

  deselectRows() {
    const itemsToBeUnselected = this.filteredEvents.connect().value;
    itemsToBeUnselected.forEach(element => {
      this.selection.deselect(element);
    });
  }

  selectRows() {
    const currentlyDisplayedRows = this.filteredEvents.connect().value;

    for (let index = 0; index < currentlyDisplayedRows.length; index++) {
      this.selection.select(currentlyDisplayedRows[index]);
      this.selectionAmount = this.selection.selected.length;
    }
  }

The HTML:

<ng-container matColumnDef="select">
  <th mat-header-cell *matHeaderCellDef>
    <mat-checkbox (change)="$event ? masterToggle() : null" [checked]="selection.hasValue() && isViewableSelected()"
      [indeterminate]="selection.hasValue() && !isViewableSelected()">
    </mat-checkbox>
  </th>
  <td mat-cell *matCellDef="let row">
    <mat-checkbox (click)="$event.stopPropagation()" (change)="$event ? selection.toggle(row) : null"
      [checked]="selection.isSelected(row)">
    </mat-checkbox>
  </td>
</ng-container>

Here is my solution. https://angular-vkz1dp.stackblitz.io I build in an extra if switch page it will uncheck.

HTML column:

<mat-checkbox #ref
       (click)="$event.stopPropagation()"
       (change)="$event ? masterToggle(ref) : null"></mat-checkbox>

HTML cell:

<mat-checkbox (click)="$event.stopPropagation()"
                    [checked]="selection.isSelected(element)"></mat-checkbox>

HTML paginator:

<mat-paginator fixed [pageSizeOptions]="[20, 50, 100]" [pageSize]="20" (page)="pageChange()" showFirstLastButtons></mat-paginator>

Component:

  @ViewChild('ref') ref: any;

  masterToggle(_ref: any) {
    if(_ref.checked){
        this.checkPageOnly();
    }
    else {
        this.selection.clear();
    }
  }

  checkPageOnly() {
      let i = this.dataSource.paginator.pageIndex * this.dataSource.paginator.pageSize;
      let end = (this.dataSource.paginator.pageIndex + 1) * this.dataSource.paginator.pageSize;
      for(i; i < end; i++) {
        this.selection.select(this.dataSource.data[i]);
      }
  }

    pageChange() {
        this.ref.checked = false;
        this.masterToggle(this.ref);
    }
}

If you're using sorting, paginating, and filtering:

HTML column:

<mat-checkbox (change)="$event ? masterToggle($event) : null"
    [checked]="selection.hasValue() && isEntirePageSelected()"
    [indeterminate]="selection.hasValue() && !isEntirePageSelected()"
    [aria-label]="checkboxLabel()"></mat-checkbox>

Component:

  getPageData() {
    return this.dataSource._pageData(this.dataSource._orderData(this.dataSource.filteredData));
  }

  isEntirePageSelected() {
    return this.getPageData().every((row) => this.selection.isSelected(row));
  }

  masterToggle(checkboxChange: MatCheckboxChange) {
    this.isEntirePageSelected() ?
      this.selection.deselect(...this.getPageData()) :
      this.selection.select(...this.getPageData());
  }

  checkboxLabel(row): string {
    if (!row) {
      return `${this.isEntirePageSelected() ? 'select' : 'deselect'} all`;
    }
    return `${this.selection.isSelected(row) ? 'deselect' : 'select'} row ${row.id + 1}`;
  }

Was able to get it to work by removin the last line on the masterToggle() method, and replacing that with a custom function that loops through the PageSize of the paginator and calls the select method of the SelectionModel for each alert it finds; I also changed the isAllSelected method to compare the PageSize and the selected lenght instead of the whole dataSource.

/** Whether the number of selected elements matches the total number of rows. */
  isAllSelected() {
    const numSelected = this.selection.selected.length;
    const page = this.dataSource.paginator.pageSize;
    return numSelected === page;
  }

  /** Selects all rows if they are not all selected; otherwise clear selection. */
  masterToggle() {
    this.isAllSelected() ? 
    this.selection.clear() : this.selectRows();
  }

  selectRows() {
    for (let index = 0; index < this.dataSource.paginator.pageSize; index++) {
      this.selection.select(this.dataSource.data[index]);
      this.selectionAmount = this.selection.selected.length;
    }
  }