1

How can we allow the users to only select one row per group?

I have the following code.

var data = [
           { ActionItemId: "AAZ08702-0001104", StrarTime: "2007-10-01", Category: "General", CategoryDetails: "dummy text of industry. a galley of type ", TargetCategory: "200.00",
            TargetDateCategory: "10.00", ActualCategory: "210.00"}
        ];

        $("#jqGrid").jqGrid({
            data: data,
            datatype: "local",
            colModel: [
                { label: 'Action Item ID', name: 'ActionItemId',  key: true },
                { label: 'Start Time', name: 'StrarTime'},
                { label: 'Category', name: 'Category'},
                { label: 'Details', name: 'CategoryDetails', cellattr: function (rowId, tv, rawObject, cm, rdata) { return 'style="white-space: normal;"' }},
                { label: 'Target <Category>', name: 'TargetCategory' },
                { label: 'Target Date <Category>', name: 'TargetDateCategory'}
            ],
            loadonce: true,
            viewrecords: true,
            //width: 1000,
            height: 400,
            rowNum: 20,
            rowList: [20, 30, 50],
            rownumbers: true,
            rownumWidth: 25,
            multiselect: true,
            shrinkToFit: false,
            pager: "#jqGridPager",
            grouping: true,
            groupingView: {
                groupField: ["Category"],
                groupColumnShow: [true],
                groupText: ["Category: <b>{0}</b>"],
                groupOrder: ["asc"],
                groupSummary: [false],
                groupCollapse: false

            }
        });

I need to disable the ability to select multiple rows per column. is it possible?

Is there a setting in the grouping function to enable which will work as mu requirement? or should it be custom development?

Note: I have only added one column to avoid a very long code in the question

ChathuraSam
  • 145
  • 2
  • 13
  • 1
    Sorry, but it's not full clear for me which behavior you need to implement. Let us the user select a row. Do you want to deny the selection if another row from the same group is already selected or you want to unselect previously selected row (from the same group) and select the currently clicked row? – Oleg Nov 16 '15 at 10:27
  • The 1st option you mentioned. example: user select a row, he cannot select anymore rows from that same group, but he can select rows from other groups. apparently the user can only select one row from each group – ChathuraSam Nov 16 '15 at 10:36
  • you can use `beforeSelectRow` callback to deny selection of any row. Inside of `beforeSelectRow` callback you can test any your custom criteria and return `false` to deny selection or return `true` to allow selection. Depend on version of jqGrid which you use it could be required to uncheck the multiselect checkbox only for the case that the user clicked *directly* on the checkbox. There are different ways how you can test whether the already selected row (from `selarrrow`) is in the same group like the currently clicked. In case of usage small page size (`selarrrow`) any way is OK. – Oleg Nov 16 '15 at 11:02
  • how can i check the currently clicked row is in which group and how can i disable selection of only that group? – ChathuraSam Nov 16 '15 at 11:17
  • @Oleg Please let me know if there is a way to uncheck other rows of the current selected row's group. i'm still stuck here. – ChathuraSam Nov 17 '15 at 08:02

2 Answers2

1

One of the possible implementation could be adding add callback which return false if another row from the same group is already selected. An example of the implementation is the following:

beforeSelectRow: function (rowid, e) {
    var selarrrow = $(this).jqGrid("getGridParam", "selarrrow"),
        $tr = $(e.target).closest("tr.jqgrow"),
        otherIdsOfTheGroup;

    if ($tr.length > 0) {
        otherIdsOfTheGroup =
            // get all rows of the group before the current
            $tr.prevUntil("tr.jqgroup")
                // add all rows of the group after the current
                .add($tr.nextUntil("tr.jqgroup"))
                // enum all the rows of the group without the current
                .map(function () {
                    // test whether the rowid is already selected
                    if ($.inArray(this.id, selarrrow) >= 0) {
                        // add the rowid to the array of returned values
                        return this.id;
                    }
                });
        // otherIdsOfTheGroup contains the array of rowids of the rows
        // from the same group, which are already selected
        if (otherIdsOfTheGroup.length > 0) {
            return false; // prevent selection
        }
    }
    return true; // allow selection
}

See the demo

UPDATED: One can easy modify the aboce vode to unselect the previously selected rows from the same group. One need just call resetSelection for every rowid from otherIdsOfTheGroup array and return true from otherIdsOfTheGroup to allow selection:

beforeSelectRow: function (rowid, e) {
    var $this = $(this),
        selarrrow = $this.jqGrid("getGridParam", "selarrrow"),
        $tr = $(e.target).closest("tr.jqgrow"),
        otherIdsOfTheGroup;

    if ($tr.length > 0) {
        otherIdsOfTheGroup =
            // get all rows of the group before the current
            $tr.prevUntil("tr.jqgroup")
                // add all rows of the group after the current
                .add($tr.nextUntil("tr.jqgroup"))
                // enum all the rows of the group without the current
                .map(function () {
                    // test whether the rowid is already selected
                    if ($.inArray(this.id, selarrrow) >= 0) {
                        // add the rowid to the array of returned values
                        return this.id;
                    }
                });
        // otherIdsOfTheGroup contains the array of rowids of the rows
        // from the same group, which are already selected
        if (otherIdsOfTheGroup.length > 0) {
            $.each(otherIdsOfTheGroup, function () {
                $this.jqGrid("resetSelection", this);
            });
        }
    }
    return true; // allow selection
}

See the next demo. I included hiding of the column header of "Select All" button just to write less code. You can implement onSelectAll callback and allow to select only one (for example the first) row from every group.

Oleg
  • 220,925
  • 34
  • 403
  • 798
  • Thanks a lot for this code. I have also tried to solve this using **beforeSelectRow** method. I will publish my solution as an answer. Issues I found In your solution, the user cannot straightaway select another row from the same group(user has to untick the current row and select another row) in my solution, user cannot unselect at all. so it works like radio button set. i guess those are the drawbacks of the two solutions we have – ChathuraSam Nov 18 '15 at 09:22
  • 1
    @ChathuraSam: You are welcome! I asked you about the exact behavior, which you need to implement in my first comment to your question. You answers: "1st option", which mean "to deny the selection if another row from the same group is already selected". Thus I implemented the behavior. In any way it's very easy to change the behavior. One can just replace the line `return false;` of my code to calling of `resetSelection` for every rows of the same group which is already selected. See **UPDATED** part of my answer. – Oleg Nov 18 '15 at 09:34
  • wow awesome. thanks a lot for the help given. you are a life saver ! – ChathuraSam Nov 18 '15 at 09:45
  • I tested your solution but it does not unselect properly. when i select few rows from few groups and then change the selection it does not deselect the previous ones. it updates in the UI properly, but when i get the selected IDs from **var selectedIDs = grid.getGridParam("selarrrow");** it shows more IDs than selected – ChathuraSam Nov 18 '15 at 10:37
  • @ChathuraSam: probably you use some other old version of jqGrid, which have a bug. I debugged [my last demo](http://www.ok-soft-gmbh.com/jqGrid/OK/groupingPreventSelection1.htm) and `selarrrow` is always `[]` (empty array) in the last line `return true; // allow selection` of `beforeSelectRow` or it could contain rowids from *other groups* only. Please retry your tests once more with my demo or with my latest version of free jqGrid (see [here](https://github.com/free-jqgrid/jqGrid/wiki/Access-free-jqGrid-from-different-CDNs#access-githib-code-from-rawgit)). – Oleg Nov 18 '15 at 10:44
  • i guess the **otherIdsOfTheGroup** does not produce the expected IDs. So even though it updates the UI properly, it does not deselect the other rows in the same group when we select one row. – ChathuraSam Nov 18 '15 at 10:45
  • yes may be that is the case, I'm using **jqGrid 4.4.4**. I will try using the latest. sorry about the trouble – ChathuraSam Nov 18 '15 at 10:48
  • @ChathuraSam: What "not works" with paging? Which demo= Which steps one should do to reproduce the problem? Please describe the exact test case: step by step instructions to reproduce the problem with the expected results and the results, which one have instead. – Oleg Nov 19 '15 at 05:41
  • http://www.ok-soft-gmbh.com/jqGrid/OK/groupingPreventSelection1.htm This demo does not work properly with paging. select something in the 1st and 2nd page and return to 2nd page, the one previously selected is not selected now – ChathuraSam Nov 19 '15 at 05:43
  • 1
    @ChathuraSam: Sorry, but I think that you are newcomer in jqGrid. It supports selection of rows **on one page** only. I implemented new option in the latest version of free jqGrid: `multiPageSelection: true`. One need add the option if one want to hold selection over multiple pages. See [the demo](http://www.ok-soft-gmbh.com/jqGrid/OK/multiPageSelection.htm) from [the answer](http://stackoverflow.com/a/33021115/315935). Is it what you need? – Oleg Nov 19 '15 at 05:45
  • 1
    @ChathuraSam: See [the modified demo](http://www.ok-soft-gmbh.com/jqGrid/OK/groupingPreventSelection2.htm). – Oleg Nov 19 '15 at 05:52
  • Awesome. Thanks a lot this is exactly what i needed. yes I am a new comer to the jqgrid. :) – ChathuraSam Nov 19 '15 at 05:55
0

I managed to solve this issue using the following code.

        beforeSelectRow: function (id, e) {
            var rowdata = $("#jqGrid").getRowData(id);
            var category = rowdata.Category;
            var selectedRowTR = $("#jqGrid").find("tr[id='" + id + "']");
            var groupTRs = $("#jqGrid").find("tbody> tr.jqgrow > td[title='" + category + "']").parents("tr");

            var ids = groupTRs.map(function () {
                return this.id;
            }).get();

            var selectedIDs = $("#jqGrid").getGridParam("selarrrow");

            var commonValues = [];
            var i, j;
            var arr1Length = ids.length;
            var arr2Length = selectedIDs.length;

            for (i = 0; i < arr1Length; i++) {
                for (j = 0; j < arr2Length; j++) {
                    if (ids[i] === selectedIDs[j]) {
                        commonValues.push(ids[i]);
                    }
                }
            }

            for (var i = 0; i < commonValues.length; i++) {
                $("#jqGrid").jqGrid('setSelection', commonValues[i], false);

            }

        return true;
    },

rowdata.Category; is the variable which the table is grouped. The only issue is that the user cannot untick what he/she has already selected in a group. so it works like a radio button set. But it works for my requirement. hopefully we can improve this and introduce radio kind of behavior for grouping in jqgrid. thanks everyone.

ChathuraSam
  • 145
  • 2
  • 13