Friday, February 25, 2011

jqGrid - customizing the multi-select option (restrict single selection and adding custom events)

Goal:

Using the jgGrid to enable a selection of a checkbox for row selection - which is easy to set in the jqGrid - but also only allowing a single row to be selectable at a time while adding events based on whether the row was selected or de-selected.

Environment:

Issue:

The jqGrid does not support the option to restrict the multi-select to only allow for a single selection. You may ask, why bother with the multi-select checkbox function if you only want to allow for the selection of a single row? Good question, as an example, you want to reserve the selection of a row to trigger another kind of event and use the checkbox multi-select to handle a different kind of event; in other words, when I select the row I want something entirely different to happen than when I select to check off the checkbox for that row.
Also the setSelection method of the jqGrid is a toggle and has no support for determining whether the checkbox has already been selected or not, So it will simply act as a switch - which it is designed to do - but with no way out of the box to only check off the box (as in not to de-select) rather than act like a switch.
Furthermore, the getGridParam('selrow') does not indicate if the row was selected or de-selected, which seems a bit strange and is the main reason for this blog post.

Solution:

How this will act:

When you check off a multi-select checkbox in the gird, and then commence to select another row by checking off that row's multi-select checkbox - I'm not talking there about clicking on the row but using the grid's multi-select checkbox - it will de-select the previous selection so that you are always left with only a single selection.
Furthermore, once you select or de-select a multi-select checkbox, fire off an event that will be determined by whether or not the row was selected or de-selected, not just merely clicked on. So if I de-select the row do one thing but when selecting it do another.

Implementation (this of course is only a partial code snippet):

            multiselect: true,
            multiboxonly: true,
            onSelectRow: function (rowId) {
                var gridSelRow = $(item).getGridParam('selrow');
                var s;
                s = $(item).getGridParam('selarrrow');
                if (!s || !s[0]) {
                    $(item).resetSelection();
                    $('#productLineDetails').fadeOut();
                    lastsel = null;
                    return;
                }
                var selected = $.inArray(rowId, s) != -1;
                if (selected) {
                    $('#productLineDetails').show();
                }
                else {
                    $('#productLineDetails').fadeOut();
                }

                if (rowId && rowId !== lastsel && selected) {
                    $(item).GridToForm(gridSelRow, '#productLineDetails');
                    if (lastsel) $(item).setSelection(lastsel, false);
                }
                lastsel = rowId;
            },

In the example code above:

The "item" property is the id of the jqGrid.
The following to settings ensure that the jqGrid will add the new column to select rows with a checkbox and also the not allow for the selection by clicking on the row but to force the user to have to click on the multi-select checkbox to select the row:
multiselect: true,

multiboxonly: true,
Unfortunately the var gridSelRow = $(item).getGridParam('selrow') function will only return the row the user clicked on or rather that the row's checkbox was clicked on and NOT whether or not it was selected nor de-selected, but it retrieves the row id, which is what we will need.
The following piece get's all rows that have been selected so far, as in have a checked off multi-select checkbox:
var s;

s = $(item).getGridParam('selarrrow');
Now determine if the checkbox the user just clicked on was selected or de-selected:
var selected = $.inArray(rowId, s) != -1;
If it was selected then show a container "#productLineDetails", if not hide that container away.
The following instruction populates a form with the grid data using the built-in GridToForm method (just mentioned here as an example) ONLY if the row has been selected and NOT de-selected but more importantly to de-select any other multi-select checkbox that may have been selected:
if (rowId && rowId !== lastsel && selected) {
                    $(item).GridToForm(gridSelRow, '#productLineDetails');
                    if (lastsel) $(item).setSelection(lastsel, false);
}

No comments:

Post a Comment