jqGrid Column Group
Asked Answered
C

3

4

can I implement a column group in jqGrid like the jQuery EasyUI library does?

You can figure out what I mean by going on the jQuery EasyUI demo web site, and choose Datagrid then Column Group from the left menu.

Thanks for helping

Candicecandid answered 7/9, 2011 at 22:40 Comment(0)
U
10

Your question is not new. Many times the corresponding feature request was asked in trirand forum or on the stackoverflow. I give another answer on the close question some time before.

Now after reading of your question I do decided don't make a perfect solution supporting all jqGrid features (which is too difficult at once). Instead of that I decide to create a solution which can be already used in many cases, but which has some restrictions.

The demo shows my first results:

enter image description here

The restrictions:

  • the columns of the grid can not be resized. I use in the demo cmTemplate: {resizable: false} parameter to set resizable: false in all grid columns.
  • sortable: true is not supported
  • showCol, hideCol or columnChooser are not currently supported, but I am sure that one can quickly fix the problems.
  • columns over which one will place an additional column header should has the same width. If the columns have different width values the total width of the column will be divided between the columns automatically.

On the other side everything work without any problem in all my tests with other popular options like shrinkToFit: false, autowidth: true or changing of the grid width with respect of setGridWidth method (with or without shrinking).

Now first about the usage of the feature. I wrote function insertColumnGroupHeader which I use in the above example as

insertColumnGroupHeader(grid, 'amount', 3, '<em>Information about the Price</em>');

It inserts an additional column header with the HTML fragment 'Information about the Price' over 3 columns starting with the column 'amount'. So the usage is pretty simple. You can of course use just any text like 'Information about the Price' as the additional column header.

The function insertColumnGroupHeader has the following code:

var denySelectionOnDoubleClick = function ($el) {
        // see https://mcmap.net/q/337195/-disable-text-highlighting-on-double-click-in-jquery-duplicate/2132230#2132230
        if ($.browser.mozilla) {//Firefox
            $el.css('MozUserSelect', 'none');
        } else if ($.browser.msie) {//IE
            $el.bind('selectstart', function () {
                return false;
            });
        } else {//Opera, etc.
            $el.mousedown(function () {
                return false;
            });
        }
    },
    insertColumnGroupHeader = function (mygrid, startColumnName, numberOfColumns, titleText) {
        var i, cmi, skip = 0, $tr, colHeader, iCol, $th,
            colModel = mygrid[0].p.colModel,
            ths = mygrid[0].grid.headers,
            gview = mygrid.closest("div.ui-jqgrid-view"),
            thead = gview.find("table.ui-jqgrid-htable>thead");

        mygrid.prepend(thead);
        $tr = $("<tr>");
        for (i = 0; i < colModel.length; i++) {
            $th = $(ths[i].el);
            cmi = colModel[i];
            if (cmi.name !== startColumnName) {
                if (skip === 0) {
                    $th.attr("rowspan", "2");
                } else {
                    denySelectionOnDoubleClick($th);
                    $th.css({"padding-top": "2px", height: "19px"});
                    $tr.append(ths[i].el);
                    skip--;
                }
            } else {
                colHeader = $('<th class="ui-state-default ui-th-ltr" colspan="' + numberOfColumns +
                    '" style="height:19px;padding-top:1px;text-align:center" role="columnheader">' + titleText + '</th>');
                denySelectionOnDoubleClick($th);
                $th.before(colHeader);
                $tr.append(ths[i].el);
                skip = numberOfColumns - 1;
            }
        }
        mygrid.children("thead").append($tr[0]);
    };

Additionally it was required to make some changes in the jqGrid code. You can download the modified version (the modification of the 4.1.2 version) of jquery.jqGrid.src.js from here. The changes consist from two blocks. First I changed the code of sortData function, the lines 1874-1884

var thd= $("thead:first",ts.grid.hDiv).get(0);
$("tr th:eq("+ts.p.lastsort+") span.ui-grid-ico-sort",thd).addClass('ui-state-disabled');
$("tr th:eq("+ts.p.lastsort+")",thd).attr("aria-selected","false");
$("tr th:eq("+idxcol+") span.ui-icon-"+ts.p.sortorder,thd).removeClass('ui-state-disabled');
$("tr th:eq("+idxcol+")",thd).attr("aria-selected","true");
if(!ts.p.viewsortcols[0]) {
    if(ts.p.lastsort != idxcol) {
        $("tr th:eq("+ts.p.lastsort+") span.s-ico",thd).hide();
        $("tr th:eq("+idxcol+") span.s-ico",thd).show();
    }
}

to the following:

var previousSelectedTh = ts.grid.headers[ts.p.lastsort].el,
    newSelectedTh = ts.grid.headers[idxcol].el;
$("span.ui-grid-ico-sort",previousSelectedTh).addClass('ui-state-disabled');
$(previousSelectedTh).attr("aria-selected","false");
$("span.ui-icon-"+ts.p.sortorder,newSelectedTh).removeClass('ui-state-disabled');
$(newSelectedTh).attr("aria-selected","true");
if(!ts.p.viewsortcols[0]) {
    if(ts.p.lastsort != idxcol) {
        $("span.s-ico",previousSelectedTh).hide();
        $("span.s-ico",newSelectedTh).show();
    }
}

Next I defined getColumnHeaderIndex function as the following

var getColumnHeaderIndex = function (th) {
    var i, headers = ts.grid.headers, ci = $.jgrid.getCellIndex(th);
    for (i = 0; i < headers.length; i++) {
        if (th === headers[i].el) {
            ci = i;
            break;
        }
    }
    return ci;
};

and changed the lines 2172 and 2185 of grid.base.js from

var ci = $.jgrid.getCellIndex(this);

to

var ci = getColumnHeaderIndex(this);

It's all. The above described changes should have no negative influence on the original jqGrid code and can be used as usual. I will publish my suggestion in the next time on trirand forum.

UPDATED: Another version of the demo allows resizing of all columns excepting the columns having the headers. In the version all the columns over which one will place an additional column header have to have the same width. The width of the columns not divided between the columns automatically. You have to set the same column width manually.

UDPATED 2: I want to inform about some progress in creating more advanced version of multiheader jqGrid. First wildraid posted very interesting solution. See his demo here. By the way if one use with the method jqGrid with the fixes which I suggested (see above) the problem with sorting icons in the demo will be solved. See here the demo as the conformation.

After that I works a little more abut reducing restrictions in my multicolumn approach which use rowSpan to increase the height of the columns. Here is my current intermediate result: the new demo. The new demo work already very good in Internet Explorer 9/8, Firefox and Opera. In Webkit-based browsers (Google Chrome and Safari) it has still the above listed restriction (column headers which has multiheaders have to have the same size and be not resizable). The demo looks good has the restrictions and it looks good in Webkit-based web browsers. Nevertheless you can see progress in the sort time.

I plan to increase the height of the resizable area used to resize the columns based on the demo from the answer. Of cause the usage of many headers over column headers will be also supported. ColumnChooser or showCol/hideCol will be supported too. The most interesting for me now is to finding a clear way how to implement multirows column headers using rowSpan in Webkit-based browsers (Google Chrome and Safari). Probably somebody else will find a solution way? It is the main reason why I decide to share not completed results here.

UPDATE 3: The changes in the code of jqGrid are included (see here) in the main code of jqGrid. I improved the solution which I described here to this and this demos. The second demo increase the grid width if the column width will be increased. I personally like the behavior.

UPDATE 4: The next version of the demo you can see here. It has an boolean option (the parameter useColSpanStyle) which which defines whether colspan should be used or not. With false value of the parameter the results will be the following.

Unflinching answered 8/9, 2011 at 16:47 Comment(11)
@Jonathan: I'm glad to hear this! My current demo is not perfect, but one step to the solution. Because you have the same question before I want to inform you about the answer.Unflinching
Indeed, it worked perfectly for me, although nowdays Im just using Razor and Data rendering syntax :-)Liederkranz
Wow! I did not expect it was so hard. Great code! Thanks Oleg, it worked perfectly :)Candicecandid
@Lorenzo: How you can read in "UPDATE 3" part there are some progress in the discussed subject. Now it's clear that the next version of jqGrid will have support of multiline column headers in some from the ways. I will continue to inform you about this.Unflinching
@Jonathan: see "UPDATE 3" and my previous comment to Lorenzo.Unflinching
Any luck solving 'If the columns have different width values the total width of the column will be divided between the columns automatically.'? I'm using similar approach by inserting an additional row above.Gurias
@jackysee: The modified version of the solution was included in the main code of jqGrid as setGroupHeaders. The solution don't has the limitations described in the first version of the column grouping. So you don't need to hold the same width of the column headers. See the demo from the answerUnflinching
is it possible to just extract 'setGroupHeader' function out of the source of current jquery release? I'm using 4.1.2.Gurias
@jackysee: Yes, it should work, but you still need modify the lines 1874-1884 of jquery.jqGrid.src.js as I describe in my answer above.Unflinching
@Unflinching All I can say is WOW, for this answer.. Thank you Dr.Jaws
Are the any solutiony for showCol, hideCol or columnChooser by group columnsTrellas
I
0

Related: jqGrid Grouping Without Subgrids?

For visual appearance only, may be you can achieve this via editing jqgrid's html output by calling a method after loading grid data. You could access the column header by "jqgh_" prefix followed by the colName value of jgrid. After you have a set of elements, you may modify them.

Not the best way obviously, but could work.

Immensity answered 8/9, 2011 at 11:2 Comment(0)
F
0

As the later versions of jqGrid, Oleg's solution has become official :)

I'm testing it on v4.4.4, but should work on every 4.x

And it supports sorting, even if the docs say otherwise (they should really update the API ref)

check the official reference here

not the first Oleg's one to get official, you must be proud mate!

Fdic answered 17/6, 2013 at 14:43 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.