【问题标题】:Mat-Table Selection only on current PageSize?仅在当前 PageSize 上的 Mat-Table 选择?
【发布时间】:2018-10-17 18:00:45
【问题描述】:

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

我试图开始工作的情况如下:如果我的paginator 上的PageSize 是“10”,我点击masterToggle 选择“所有”行,我想要那个选择当前页面上的所有行,仅此而已,这将是与当前 PageSize 一起显示的 10 行,但是,这会选择大约 300 条记录的表的整个 dataSource

有没有办法让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));
  }

【问题讨论】:

    标签: angular typescript datatable angular-material


    【解决方案1】:

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

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

    【讨论】:

      【解决方案2】:

      能够通过删除 masterToggle() 方法的最后一行并将其替换为循环遍历分页器的 PageSize 并调用 SelectionModelselect 方法的自定义函数来使其工作它发现的每个警报;我还更改了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;
          }
        }
      

      【讨论】:

      • 在将排序应用于数据表时,我们有什么办法可以让它工作吗?应用排序时,上述解决方案有效,但它选择的记录不在排序数据上,而是在其内部 DATA 属性中加载。结果,它选择随机复选框
      • 到目前为止我还没有尝试过,我知道目前我的选择将按索引进行选择,因此在对索引进行排序时会发生变化,例如 index 0 可以像表中的第 10 行, 其余 9 个不加勾选,肯定可以做到,我会看看我是否稍后尝试测试
      • 换页怎么办?你的逻辑不行。
      • @SrichandradeepC 如果您的意思是从第 1 页更改为第 2 页,是的,选择将不再存在,如果您的意思是增加页面大小,则选择仍然存在
      • 是的,前者。我只是想通知那些寻找不同通用解决方案的用户。
      【解决方案3】:

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

        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>
      

      【讨论】:

        【解决方案4】:

        这是我的解决方案。 https://angular-vkz1dp.stackblitz.io 如果切换页面,我会添加一个额外的,它将取消选中。

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

        【讨论】:

          【解决方案5】:
                    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>
          

          【讨论】:

            【解决方案6】:

            刚刚找到this answer

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

            所以从你的代码中你可以做到:

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

            【讨论】:

              【解决方案7】:

              我找到了一种更简单的方法(Angular):
              而不是 this.dataSource.data.length 将其更改为 this.dataSource.connect().value.forEach(row =&gt; 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”是你的原始页面大小,在你的数据源没有被初始化之前定义。

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2021-11-14
                • 1970-01-01
                • 2018-07-21
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多