我知道这是一个老问题,但我必须实施这个问题,并且建议的解决方案并未涵盖所有用例(例如,@fbuchinger 建议的解决方案在用户转到最后一页时会删除一些选择,而无需执行任何操作选择,然后返回第一页)。
为了解决这个问题,我不得不做一个更复杂的实现,我什至不得不添加一个新的 DataView 事件onBeforePagingInfoChanged 并修改了 SlickGrid 事件onSelectedRowsChanged 来返回之前的行选择(在当前选择)。这些更改是在 6pac/SlickGrid 分支中进行的,并在版本 2.4.18 下发布
我在使用分页时使用的步骤如下,我们不能只使用getSelectedRows(),因为这只会返回当前页面中的选择,这还不够,我们需要保留一个带有数据对象ID的全局数组(不是行索引,因为它会在页面中不断变化),为了同时保留网格索引和数据 ID,我们将在 dataView.mapIdsToRows() 和 dataView.mapRowsToIds() 之间交替。
下图代码的步骤如下
- 更改行选择时,如果新选择尚未在所选 ID 的全局数组中,我们将添加它
- 删除行选择时,我们将从选定 ID 的全局数组中删除选择(除非它来自页面更改)
- 在我们改变页面之前,我们会用一个标志来跟踪(这个标志将用于在我们改变页面时跳过任何删除)
- 页面更改后,我们将进行额外(和延迟)检查,以确保我们在选定 ID 的全局数组中的内容显示在屏幕上
// global variables
_selectedRowDataContextIds = []; // used with row selection
_wasRecheckedAfterPageChange = true; // used with row selection & pagination
function bindSlickgridEventsForRowSelectionWithPagination() {
this._eventHandler.subscribe(this._dataView.onBeforePagingInfoChanged, () => {
this._wasRecheckedAfterPageChange = false; // reset the page check flag, to skip deletions on page change (used in code below)
});
this._eventHandler.subscribe(this._dataView.onPagingInfoChanged, () => {
// when user changes page, the selected row indexes might not show up
// we can check to make sure it is but it has to be in a delay so it happens after the first "onSelectedRowsChanged" is triggered
setTimeout(() => {
const shouldBeSelectedRowIndexes = this._dataView.mapIdsToRows(this._selectedRowDataContextIds);
const currentSelectedRowIndexes = this._grid.getSelectedRows();
if (!isequal(shouldBeSelectedRowIndexes, currentSelectedRowIndexes)) {
this._grid.setSelectedRows(shouldBeSelectedRowIndexes);
}
});
});
this._eventHandler.subscribe(this._grid.onSelectedRowsChanged, (e, args) => {
if (Array.isArray(args.rows) && Array.isArray(args.previousSelectedRows)) {
const newSelectedRows = args.rows;
const prevSelectedRows = args.previousSelectedRows;
const newSelectAdditions = newSelectedRows.filter((i) => prevSelectedRows.indexOf(i) < 0);
const newSelectDeletions = prevSelectedRows.filter((i) => newSelectedRows.indexOf(i) < 0);
// deletion might happen when user is changing page, if that is the case then skip the deletion since it's only a visual deletion
// if it's not a page change (when the flag is true), then proceed with the deletion in our global array of selected IDs
if (this._wasRecheckedAfterPageChange && newSelectDeletions.length > 0) {
const toDeleteDataIds = this._dataView.mapRowsToIds(newSelectDeletions);
toDeleteDataIds.forEach((removeId) => this._selectedRowDataContextIds.splice(this._selectedRowDataContextIds.indexOf(removeId), 1));
}
// if we have newly added selected row(s), let's update our global array of selected IDs
if (newSelectAdditions.length > 0) {
const toAddDataIds = this._dataView.mapRowsToIds(newSelectAdditions) || [];
toAddDataIds.forEach((dataId) => {
if (this._selectedRowDataContextIds.indexOf(dataId) === -1) {
this._selectedRowDataContextIds.push(dataId);
}
});
}
this._wasRecheckedAfterPageChange = true;
// form our full selected row IDs, let's make sure these indexes are selected in the grid, if not then let's call a reselect
// this could happen if the previous step was a page change
const shouldBeSelectedRowIndexes = this._dataView.mapIdsToRows(this._selectedRowDataContextIds);
const currentSelectedRowIndexes = this._grid.getSelectedRows();
if (!isequal(shouldBeSelectedRowIndexes, currentSelectedRowIndexes)) {
this._grid.setSelectedRows(shouldBeSelectedRowIndexes);
}
const newSelections = { gridRowIndexes: this._grid.getSelectedRows(), dataContextIds: this._selectedRowDataContextIds };
}
});
}
所以在这段代码中,变量this._selectedRowDataContextIds 具有完整的选定数据对象ID 集。这是一种复杂的方法,但这就是我迄今为止发现的使用网格分页的方法。
请注意,代码中只有 1 个 lodash 函数 isequal 用于比较 2 个数组,其他所有内容都是用 ES6 和 TypeScript 编写的(尽管我删除了这些类型以提高可读性)