根本是使用selectionModel,它本身储存的选中项就是一个能够不随切换分页而变化。这样太好了,
import { SelectionModel } from "@angular/cdk/collections";
而表格的dataSource是会随分页变的,此前储存的选中项就匹配不上切换分页再切换回来的项。
要做的只是:
1.监听多选框选中的变化 ,储存它,并在切换分页后,把已经存好的拿出来。
2.再细节优化就是html上是否全选本页,通过在储存的选中项目加上pageIndex本页属性,就可以通过属性判断是否本页的来设置未决定状态。
- component.ts
import { SelectionModel } from "@angular/cdk/collections"; import { MatTableDataSource } from "@angular/material/table"; import { Component, OnInit } from "@angular/core"; export class SingleCommodityManageComponent implements OnInit { dataSource = new MatTableDataSource<any>([]);//表格 selection = new SelectionModel<any>(true, []); selectedIds: any[] = []; // 存储选中项 ID 的数组 ngOnInit(): void { this.queryCommidityInfo(); this.selection.changed.subscribe((changes) => { const { added, removed } = changes; if (removed.length > 0) { // 创建一个 Set 来存储 removed 项的 comUUID const removedComUUIDs = new Set(removed.map((item) => item.comUUID)); // 直接使用 filter 方法移除匹配的项,并创建一个新数组 this.selectedIds = this.selectedIds.filter( (item) => !removedComUUIDs.has(item.comUUID) ); } if (added.length > 0) { const addedItems = added.map((item) => ({ comUUID: item.comUUID, pageIndex: this.options.pageIndex, })); this.selectedIds = this.selectedIds.concat(addedItems); } }); } // 分页器变化 paginatorChange(val) { // this.options.pageIndex = val.pageIndex; //this.options.numPerPage = val.pageSize; this.queryCommidityInfo(); } // 分页查询商品信息 queryCommidityInfo() { //...调接口 this.reshowCheckedItems();//复显已勾选 } // 多选函数 /* 重新在页面显示之前已经添加到选中的项 */ reshowCheckedItems() { this.dataSource.data.forEach((row) => { if ( this.selectedIds.some( (selectedItem) => selectedItem.comUUID === row.comUUID//如果数据为被选中的 ) ) { const oldItem = this.selection.selected.find(//找到selected旧数据的项 (item) => item.comUUID == row.comUUID ); if (oldItem) { this.selection.deselect(oldItem); // 给原来的selected旧数据设置为不选中 } this.selection.select(row); // 给新的dataSource设置为选中 } }); } /* 本页是否全选 */ isThisPageAllSelected() { const numRows = this.dataSource.data.length; const thisPageSelected = this.selectedIds.filter( (item) => item.pageIndex == this.options.pageIndex ).length; return thisPageSelected === numRows; } /* 本页是否部分选择中 */ isThisPageSomeSelected() { const isSomeSelected = this.selectedIds.some( //some() 方法测试数组中是否至少有一个元素通过了由提供的函数实现的测试。如果在数组中找到一个元素使得提供的函数返回 true,则返回 true;否则返回 false (item) => item.pageIndex == this.options.pageIndex ); return isSomeSelected; } /*本页全选*/ masterToggle() { if (this.isThisPageAllSelected()) { const thisPageSelectedIds = new Set( this.selectedIds .filter((item) => item.pageIndex === this.options.pageIndex) .map((item) => item.comUUID) //集合(Set) 是一种用于存储一组不同元素的数据结构 ); //获取当前页码 this.selection.selected.forEach((selectedItem) => { if (thisPageSelectedIds.has(selectedItem.comUUID)) { this.selection.deselect(selectedItem); //取消选中 } }); return; } this.selection.select(...this.dataSource.data); } }
2.html
<table mat-table [dataSource]="dataSource" class="mat-elevation-z0">
<ng-container matColumnDef="select">
<th mat-header-cell *matHeaderCellDef>
<mat-checkbox
color="primary"
(click)="$event.stopPropagation()"
(change)="$event ? masterToggle() : null"
[checked]="selection.hasValue() && isThisPageAllSelected()"
[indeterminate]="
isThisPageSomeSelected() && !isThisPageAllSelected()
"
>
</mat-checkbox>
</th>
<td mat-cell *matCellDef="let row">
<mat-checkbox
color="primary"
(click)="$event.stopPropagation()"
(change)="$event ? selection.toggle(row) : null"
[checked]="selection.isSelected(row)"
>
</mat-checkbox>
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="tableColumnArr"></tr>
<tr
mat-row
*matRowDef="let row; columns: tableColumnArr"
(click)="selection.toggle(row)"
></tr>
</table>
<div class="d-flex flex-row align-items-center">
<div>
已选中:{{ this.selectedIds.length }}
<span class="ml-3"> 全部:{{ this.options.totalCount }}</span>
</div>
<div class="spacer"></div>
<mat-paginator
showFirstLastButtons
[pageSizeOptions]="pageSizeOptions"
[length]="options.totalCount"
[pageIndex]="options.pageIndex"
[pageSize]="options.numPerPage"
(page)="paginatorChange($event)"
></mat-paginator>