10

Checking checkboxes across pages in jqGrid wipes out the selected checkboxes. So, if I check some checkboxes on page 1 and then click Next to go to page 2 and then come back to page 1, the selected checkboxes are no longer checked.

Is there a way in jqgrid to handle this on the client side?

techlead
  • 779
  • 7
  • 24
  • 44

1 Answers1

16

The first part of the answer contain the answer on your question. A little improved version of the demo you can find here.

If you don't need to sort by "multiselect" column the demo do what you need. Some small remarks about the demo: The checkbox over the "multiselect" column select/unselect all rows only on the current page. If you want another behavior, the code will be even more simple. I included in the demo selection of 3 items directly by loading the grid. Two items will be selected on the first page and one item on the second page. In some situation the behavior can be interesting. If you don't need this you should just comment the line idsOfSelectedRows = ["8", "9", "10"];

Below you will find the most important parts of the code of the demo

var $grid = $("#list"), idsOfSelectedRows = [],
    updateIdsOfSelectedRows = function (id, isSelected) {
        var index = $.inArray(id, idsOfSelectedRows);
        if (!isSelected && index >= 0) {
            idsOfSelectedRows.splice(index, 1); // remove id from the list
        } else if (index < 0) {
            idsOfSelectedRows.push(id);
        }
    };

// initialize selection
idsOfSelectedRows = ["8", "9", "10"];

$grid.jqGrid({
    datatype: 'local',
    // ... other parameters
    multiselect: true,
    onSelectRow: updateIdsOfSelectedRows,
    onSelectAll: function (aRowids, isSelected) {
        var i, count, id;
        for (i = 0, count = aRowids.length; i < count; i++) {
            id = aRowids[i];
            updateIdsOfSelectedRows(id, isSelected);
        }
    },
    loadComplete: function () {
        var $this = $(this), i, count;
        for (i = 0, count = idsOfSelectedRows.length; i < count; i++) {
            $this.jqGrid('setSelection', idsOfSelectedRows[i], false);
        }
    }
});

If you want you can consider to hold idsOfSelectedRows as an additional parameter of jqGrid. Currently there are no validation of jqGrid parameters and you can extend there. The advantage will be persistence of idsOfSelectedRows together with the corresponding jqGrid.

UPDATED: Free jqGrid fork of jqGrid supports multiPageSelection: true option which can be combined with multiselect: true option. It allows to hold the parameter selarrrow (the list of ids of selected rows) over many pages. By default jqGrid reset the array selarrrow during paging, but in case of usage multiPageSelection: true, multiselect: true it doesn't so resetting. Moreover it preselects all rows from selarrrow array during the building the page. Thus if one fills selarrrow array with all rowids of the items (all rows over all pages) then the rows will be displayed selected. The user still can deselect some rows and jqGrid will not change the changes made by the user.

The demo, created for the answer, shows the usage of multiPageSelection: true in free jqGrid. Another answer describes shortly other new options of free jqGrid: multiselectPosition: "right", which allows to move the column of multiselect checkboxes to the right, multiselectPosition: "none", which allows use multiselect functionality without any multiselect column and hasMultiselectCheckBox callback, which can be used to create multiselect checkboxes not in all rows of jqGrid.

Community
  • 1
  • 1
Oleg
  • 220,925
  • 34
  • 403
  • 798
  • 1
    Oleg, thank you so much for this! However, I found a small bug (I haven't tried to fix it yet but will try tomorrow :))- if you check several boxes and then uncheck at least two, the checkboxes are no longer in 'idsOfSelectedRows' and checked boxes are not maintained through paging. – icats Nov 17 '11 at 23:38
  • 2
    Additionally, would you recommend that I use the 'idsOfSelectedRows' (as gathered in your example) to gather all selected row ids across the pages for use to post to some server action? Thanks!! – icats Nov 18 '11 at 00:30
  • 2
    Oh, sorry, one more thing :). When reloading the grid (`$grid.jqGrid('setGridParam',{datatype:'json'}).trigger('reloadGrid');`), should I clear out the idsOfSelectedRows array manually? Or is there some sort of event I can use to do this? Thanks again :) – icats Nov 18 '11 at 00:34
  • 1
    @icats: Thank you! The posted code had bugs which are fixed now. About communication with the server it's a good point. I think it could be helpful to post the `idsOfSelectedRows` in postData. For example like `postData: {selectedIds: function() { return idsOfSelectedRows.join(','); }}`. If the grid need be reloaded with clearing the data the `idsOfSelectedRows` array have to be reset manually. If the feature would be in the main code of jqGrid one could do this automatically. Everywhere where one do `ts.p.data = [];` in the code one should clear `idsOfSelectedRows` too. Thanks you for advice – Oleg Nov 18 '11 at 08:38
  • Thanks again Oleg, this worked great! One other thing I thought of- the 'select all' checkbox on the top of the multiselect checkbox column. This will need to add all IDs to the array (well, all the IDs that haven't been checked yet). I guess the `onSelectRow` event is not triggered for each row selected, which makes sense I guess as it would be kind of expensive :). I think my users would like for the 'select all' to only select all the rows on the focused page. I'll work on it and post (first issue- detecting clicks on the select all box), but you may have a better method of this :). – icats Nov 18 '11 at 17:01
  • I have a partial solution: part 1: `$(document).on('change', '#cb_commonDocumentsSearchResultsGrid', function (e) { //selecting all rows on page if ( $(this).is(":checked") ) { $.each ($searchResultsGrid.getGridParam('selarrrow'), function() { //if not in id not already in selected row array, then add it if ( $.inArray(this.toString(), idsOfSelectedRows) == -1 ) { idsOfSelectedRows.push(this.toString()); } }); }` – icats Nov 18 '11 at 20:08
  • part2: `//unselecting all rows on page else { //go through each row in the grid and remove its id from the idsOfSelectedRows array $.each ($searchResultsGrid.jqGrid('getDataIDs'), function() { var gridDataId = this.toString(); //if the current grid id is in the idsOfSelectedRows array, //then remove it from the idsOfSelectedRows if ( $.inArray(gridDataId, idsOfSelectedRows) != -1 ) { idsOfSelectedRows = $.grep(idsOfSelectedRows, function(value) { return value != gridDataId; }); } }); } });` – icats Nov 18 '11 at 20:09
  • My code will maintain the `idsOfSelectedRows` array for selecting all/deselecting all rows by clicking on the 'select all' checkbox on the top of the multiselect checkbox column. However, I think that this part in the `loadComplete` code you gave is making it so the selected rows are not re-selected upon paging: ` if ('cb' in item && item.cb) {` - I'm not sure what this code means yet... – icats Nov 18 '11 at 20:11
  • I will post a demo later of what I did to maintain checked state when using the select all/select none checkbox on the multiselect checkbox column. It involves maintaining the row's 'cb' attribute and the idsOfSelectedRows array consistent with each other. – icats Nov 18 '11 at 21:10
  • @icats: If you don't need to sort by 'cb' (multiselect) column you should remove the code which `item.cb`, `'cb' in item` and so on from `onSelectRow` and from `loadComplete`. Then your code should work correctly. – Oleg Nov 18 '11 at 21:15
  • @icats: Instead of `$(document).on('change', '#cb_commonDocumentsSearchResultsGrid', function (e) {...` you can use `onSelectAll` callback of jqGrid. – Oleg Nov 18 '11 at 21:26
  • @icats: I make [another demo](http://www.ok-soft-gmbh.com/jqGrid/SimpleLocalGridWithPermanentMultiselect3.htm) which you need and updated my answer. – Oleg Nov 18 '11 at 22:32
  • @Oleg: I have another interesting scenario - http://stackoverflow.com/questions/8291322/jqgrid-attaching-a-plugin-to-a-table-cell-when-in-inline-edit-mode – techlead Nov 28 '11 at 03:48
  • @Oleg: I get an **error message in IE at line 43** when I select a row **using your demo** - http://www.ok-soft-gmbh.com/jqGrid/SimpleLocalGridWithPermanentMultiselect3.htm – techlead Dec 28 '11 at 04:12
  • @SK11: Thank you! I didn't tested the code in old versions of the web browsers. I fixed the problem by replacing of `idsOfSelectedRows.indexOf(id)` to `$.inArray(id, idsOfSelectedRows)`. I updated [the demo](http://www.ok-soft-gmbh.com/jqGrid/SimpleLocalGridWithPermanentMultiselect3.htm). – Oleg Dec 29 '11 at 11:17
  • (Three years later..) Unbelievable that jqGrid STILL doesn't support persisting checkbox values when paging, out of the box. This code comes close to fixing the problem, but I find it merely steps through selecting each of my previously ticked rows.. one by one.. but doesn't actually tick any of the row's checkboxes. – Mike Gledhill Jun 13 '14 at 14:21
  • 1
    @MikeGledhill: I agree with you, but I'm not an owner of the code of jqGrid. I posted many my suggestions to Tony. The most from there were accepted and they are a part of jqGrid, but someone (like persistent selections) isn't. By the way one can use `idsOfSelectedRows` as *new option* on jqGrid. If you define it like any other properties (`multiselect: true, idsOfSelectedRows: [], onSelectRow`) you would be ably access the property as `this.p.idsOfSelectedRows` inside of any jqGrid callback (`onSelectRow`, `onSelectAll` ...) or as `$(this).jqGrid("getGridParam", "idsOfSelectedRows")`. – Oleg Jun 13 '14 at 15:44
  • @MikeGledhill: By the way, I would recommend you to read [the answer](http://stackoverflow.com/a/8436273/315935) and [this one](http://stackoverflow.com/a/8547852/315935) which describes how to use `localStorage` to make many options of jqGrid persistent. [The demo](http://www.ok-soft-gmbh.com/jqGrid/ColumnChooserAndLocalStorage2_.htm) holds selected rows over **multiple visits of the same page**. It holds filters, sorting and other information. It can improve users comfort of the usage of jqGrid. – Oleg Jun 13 '14 at 15:50
  • (Ooops, what have I started !) Sorry, no criticism intended - your code saved me from a lot of headscratching. It's just amazing that this functionality doesn't come as standard with jqGrid itself. It's very easy for JavaScript to become lengthy and hard to maintain. Having to add this same "fix" to each page where I want to add jqGrid checkboxes is disappointing, that's all. Thanks again for your suggestions. – Mike Gledhill Jun 16 '14 at 09:53