Angular Material Table 使用选择模型和服务器端分页
Angular Material Table with Selection Model and server side pagination
我有一个 Angular Material table
和 pagination
和一个 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;
}
我有一个 Angular Material table
和 pagination
和一个 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;
}