jqGrid - saving checkbox selected state
Asked Answered
A

1

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?

Autochthon answered 17/11, 2011 at 18:14 Comment(0)
P
17

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.

Patten answered 17/11, 2011 at 19:0 Comment(19)
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.Speak
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!!Speak
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 :)Speak
@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 advicePatten
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 :).Speak
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()); } }); }Speak
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; }); } }); } });Speak
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...Speak
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.Speak
@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.Patten
@icats: Instead of $(document).on('change', '#cb_commonDocumentsSearchResultsGrid', function (e) {... you can use onSelectAll callback of jqGrid.Patten
@icats: I make another demo which you need and updated my answer.Patten
@Oleg: I have another interesting scenario - #8291822Autochthon
@Oleg: I get an error message in IE at line 43 when I select a row using your demo - ok-soft-gmbh.com/jqGrid/…Autochthon
@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.Patten
(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.Headrick
@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").Patten
@MikeGledhill: By the way, I would recommend you to read the answer and this one which describes how to use localStorage to make many options of jqGrid persistent. The demo 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.Patten
(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.Headrick

© 2022 - 2024 — McMap. All rights reserved.