Angular Material Table 使用选择模型和服务器端分页

Angular Material Table with Selection Model and server side pagination

我有一个 Angular Material tablepagination 和一个 selection model 来获取一些行来做一些事情。 目前,我正在将 pagination 更改为 server-side pagination,但我的选择模型因此失效。当我更改页面时,我可以将行添加到选择模型,并且工作正常。但是当我返回到上一页时,行(在选择模型中)并未显示为已选中。

我的选择模型,方法和angular material的demo页面公布的一样:

  selection = new SelectionModel<ItemManagementViewDTO>(true, []);

  isAllSelected(): boolean {
    const numSelected = this.selection.selected?.length;
    const numRows = this.items?.length;
    return numSelected === numRows;
  }
 

  masterToggle(): void {
    this.isAllSelected() ? this.selection.clear() : this.items?.forEach(row => this.selection.select(row));
  }

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

html很简单:

  <table mat-table [dataSource]="items" class="mat-elevation-z8" matSort>
        <!-- Checkbox Column -->
        <ng-container matColumnDef="select">
          <th mat-header-cell *matHeaderCellDef>
            <mat-checkbox
              (change)="$event ? masterToggle() : null"
              [checked]="selection.hasValue() && isAllSelected()"
              [indeterminate]="selection.hasValue() && !isAllSelected()"
              [aria-label]="checkboxLabel()"
              color="primary"
            >
            </mat-checkbox>
          </th>
          <td mat-cell *matCellDef="let row">
            <mat-checkbox (click)="$event.stopPropagation()" (change)="$event ? selection.toggle(row) : null" [checked]="selection.isSelected(row)" [aria-label]="checkboxLabel(row)" color="primary">
            </mat-checkbox>
          </td>
        </ng-container>
<!-- ... -->
<mat-paginator [length]="totalItems" (page)="onPageChange($event)" [pageSizeOptions]="[5, 10, 20]" showFirstLastButtons></mat-paginator>

我的 OnPageChange server-side 分页是:

  onPageChange(event: PageEvent): void {
    this.itemsServ.getPaginatedItems(this.paramsStored, event.pageIndex, event.pageSize).subscribe(r => {
      this.items = r.listDTO;
      this.totalItems = r.totalElements;
  }

我错过了什么?每次我更改页面时,源都会刷新,但该项目仍然存在于选择模型中(如果我添加了它)。如果它与上次通话中的项目相同,为什么没有显示为已选中?

提前致谢!

SelectionModel 在内部使用 Set 来存储所有选定的元素。

SelectionModel.isSelected 方法使用 Set.has 方法,其中 returns 一个布尔值指示是否元素存在于 Set.

这是一个示例,如果您将 Set.has 与不同的对象引用一起使用,会发生什么情况。

var set1 = new Set();
var obj1 = {'key1': 1};
set1.add(obj1);

set1.has(obj1);        // returns true
set1.has({'key1': 1}); // returns false because they are different object references

在你的情况下,如果你来回切换,table 具有相同的数据但不同的引用。

一种解决方案是 replace/remove 将所选项目与新项目一起使用。

onPageChange(event: PageEvent): void {
     this.itemsServ.getPaginatedItems(this.paramsStored, event.pageIndex, event.pageSize).subscribe(r => {
     this.items = r.listDTO;
     // replace old selected items with new ones
     const itemsToAdd= items.
           filter(item=> {
              const foundItem = this.selection.selected.find(selectedItem=> selectedItem.id === item.id);
              if(!foundItem) return;
              // removes item from selection
              this.selection.deselect(foundItem);
              return item;
           });
      
     this.selection.select(itemsToAdd);
     this.totalItems = r.totalElements;

}