仅在当前PageSize上进行Mat-Table选择?

时间:2018-10-17 18:00:45

标签: angular typescript datatable angular-material

我正在建立一个带有分页的表,该表根据一组选定的复选框来处理一些动作;我有docs,到目前为止,只选择了几行中的所有行,一切都很好;

我要开始工作的场景如下:如果我在PageSize上的paginator是“ 10”,并且我单击masterToggle以选择“全部”行,我希望选择当前页面上的所有行,仅此而已,这就是当前PageSize所显示的10行,但是,这会选择整个dataSource表中大约有300条记录。

是否有一种方法可以使masterToggle仅选择基于PageSize显示的行?然后,如果我将PageSize更改为20,则只有前10个保持选中状态。

这是我的代码。

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

  /** Selects all rows if they are not all selected; otherwise clear selection. */
  masterToggle() {
    this.isAllSelected() ?
        this.selection.clear() :
        this.dataSource.data.forEach(row => this.selection.select(row));
  }

7 个答案:

答案 0 :(得分:5)

如果您使用排序,分页和过滤:

HTML列:

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

组件:

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

答案 1 :(得分:1)

通过删除masterToggle()方法的最后一行,并用循环遍历分页器PageSize并调用select方法的自定义函数来替换它,可以使其工作SelectionModel为其发现的每个警报;我还更改了isAllSelected方法,以比较PageSize和选定的lenght而不是整个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;
    }
  }

答案 2 :(得分:1)

我的解决方案基于当前显示的行,因此可以在分页方面使用。 有很多需要改进的地方,请随时进行改进。

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

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>

答案 3 :(得分:1)

这是我的解决方案。 https://angular-vkz1dp.stackblitz.io 我内置了一个额外的if开关页面,它将取消选中。

HTML列:

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

HTML单元格:

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

HTML分页器:

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

组件:

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

答案 4 :(得分:0)

          isAllSelected() {
              // const numSelected = this.selection.selected.length;
              // const numRows = this.dataSource.data.length;
              // return numSelected === numRows;
              // const page = this.dataSource.paginator.pageSize;
              // return numSelected === page;
              return this.selection.selected.length > 0;
            }

            /** Selects all rows if they are not all selected; otherwise clear selection. */
            masterToggle() {
              this.isAllSelected() ?
                this.selection.clear() :
                // this.dataSource.data.forEach(row => this.selection.select(row));
                this.selectRows();
            }
            pageChanged(event) {
              this.selection.clear();
            }
            selectRows() {

              const intIndex = this.dataSource.paginator.pageIndex === 0 ? 0 : (this.dataSource.paginator.pageSize * this.dataSource.paginator.pageIndex);
              let intPageSize = intIndex + this.dataSource.paginator.pageSize;
              if (intPageSize > this.dataSource.filteredData.length) {
                intPageSize = this.dataSource.filteredData.length;
              }
              for (let index = intIndex; index < intPageSize; index++) {
                this.selection.select(this.dataSource.filteredData[index]);
                // this.selectionAmount = this.selection.selected.length;
              }
            }


            /** The label for the checkbox on the passed row */
            checkboxLabel(row?: TicketMatchingElement): string {
              if (!row) {
                return `${this.isAllSelected() ? 'select' : 'deselect'} all`;
              }
              return `${this.selection.isSelected(row) ? 'deselect' : 'select'} row ${row.bookingId + 1}`;
            }
            formatDateValue(dateValue: Date) {
              return formatDate(dateValue);
            }
          }

HTML仅在分页中更改

<mat-paginator [pageSizeOptions]="[5, 10, 20,25]"
        showFirstLastButtons (page)="pageChanged($event)"
      ></mat-paginator>

答案 5 :(得分:0)

刚刚找到this answer

您可以使用 datasource.connect().value 获取当前在您的表格中呈现的所有项目。

因此,根据您的代码,您可以:

masterToggle() {
    this.isAllSelected() ?
        this.selection.clear() :
        this.dataSource.connect().value.forEach(row => this.selection.select(row));
  }

答案 6 :(得分:0)

我找到了一种更简单的方法(Angular):
而不是 this.dataSource.data.length 将其更改为 this.dataSource.connect().value.forEach(row => this.selection.select(row));
类似的东西:

  masterToggle() {
    this.isAllSelected() ?
    this.selection.clear() :
    this.dataSource.connect().value.forEach(row => this.selection.select(row));
  }

但这里唯一的问题是,它不会清除所有选定的字段;所以要实现这一点,请更改您的 isAllSelected() 方法:

  isAllSelected() {
    const numSelected = this.selection.selected.length;
    const numRows = this.dataSource.paginator != undefined ? this.dataSource.paginator.pageSize : 5;
    return numSelected === numRows;
 }

这里的“5”是您的原始页面大小,在您的数据源未初始化之前定义。