I know this is an old question but I had to implement this and the proposed solution didn't cover all use case (for example, the proposed solution by @fbuchinger removes some selection if user goes to last page, without doing any selections, and comes back to first page).
To deal with this issue, I had to do a much more complex implementation and I even had to add a new DataView event onBeforePagingInfoChanged
and also modified the SlickGrid event onSelectedRowsChanged
to also return previous row selections (on top of current selections). These changes were made in the 6pac/SlickGrid fork and were released under version 2.4.18
The steps I used are the following when using Pagination, we can't just use the getSelectedRows()
since this will only return the selection in current page which is not enough, we need to keep a global array with data object IDs (not the row indexes since that will keep changing in a page), to keep both the grid indexes and the data IDs, we'll alternate between dataView.mapIdsToRows()
and dataView.mapRowsToIds()
.
The steps of the code shown below are the following
- when changing a row selection, we'll add the new selection if it's not yet in the global array of selected IDs
- when deleting a row selection, we'll remove the selection from our global array of selected IDs (unless it came from a page change)
- before we change page, we'll keep track with a flag (this flag will be used to skip any deletion when we're changing page)
- after the page is changed, we'll do an extra (and delayed) check to make sure that what we have in our global array of selected IDs is displayed on screen
// 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 };
}
});
}
So in this code, the variable this._selectedRowDataContextIds
has the full set of selected data object IDs. It's a complex approach but that is what I found so far to be working with a grid Pagination.
Note that there's only 1 lodash
function isequal
that is used in the code to compare 2 arrays, everything else is written in ES6 and TypeScript (though I removed the types to be more readable)