Adding more than two columng group headers in jqgrid
Asked Answered
V

2

9

multi level group headers in jqgrid

This is a direct response to the answer listed in the above question, but I can't add to that conversation.

I understand that there is a limitation in jqgrid to only allow one level of group headers in the grid, but I was curious if anyone has found a workaround that will allow more? We are trying to move our application from an HTML table served by the server over to jqgrid, but allowing multiple (more than 2) column headers has been deemed a critical item

Vexation answered 23/9, 2013 at 22:3 Comment(0)
S
12

Another and easy way of increasing any number of levels(dimensions) in Jqgrid is by adding setGroupHeaders that number of times

If my columns are like, ColNames = ['Id','Date', 'Client', 'Amount','Tax','Total','Notes'];

Now add setGroupHeaders Like

jQuery("#list").jqGrid('setGroupHeaders', {
          useColSpanStyle: true, 
          groupHeaders:[
            {startColumnName: 'id', numberOfColumns: 1, titleText: '.'},
            {startColumnName: 'date', numberOfColumns: 8, titleText: 'Nice'},
            ]   
        });
        jQuery("#list").jqGrid('setGroupHeaders', {
          useColSpanStyle: true, 
          groupHeaders:[
            {startColumnName: 'id', numberOfColumns: 1, titleText: '.'},
            {startColumnName: 'date', numberOfColumns: 4, titleText: 'rice'},
            {startColumnName: 'total', numberOfColumns: 2, titleText: 'dice'}
            ]   
        });

        jQuery("#list").jqGrid('setGroupHeaders', {
          useColSpanStyle: true, 
          groupHeaders:[
            {startColumnName: 'id', numberOfColumns: 1, titleText: '.'},
            {startColumnName: 'date', numberOfColumns: 2, titleText: 'Price'},
            {startColumnName: 'amount', numberOfColumns: 2, titleText: 'Shiping'},
            {startColumnName: 'total', numberOfColumns: 2, titleText: 'bipping'}
            ]   
        });

Following is the output

| .  |                       Nice                              |
----------------------------------------------------------------
| .  |                 rice                |       dice        |
----------------------------------------------------------------    
| .  |       Price     |      Shipping     |       bipping     | 
----------------------------------------------------------------    
| id |  Date  | Client |  Amount   |  Tax  | Total  |  Notes   |   
Spoonfeed answered 3/6, 2014 at 13:20 Comment(3)
This is the better answer. Thanks for adding it!Vexation
@ThomasMondelli: Do you tested the above code? Is the results of the demo what you want?Amoretto
Yes, I've completed a small test case and it works as described. Because it uses jqGrid's functionality, it is a much simpler way to do it and the results better match the rest of the table.Vexation
A
6

The reason of restriction of one level of group headers in jqGrid exist because jqGrid provide more as just displaying the headers. You can see on the example of the demo created for the answer that the column headers after grouping are clickable (to sort by the column) and resizable (by drag&drop on the separator between column headers). If you use titleText option of setGroupHeaders you can include HTML fragments, inclusive <table> element, in the column header. It gives you the possibility to display milti-level headers. One can include resizable: false to deny resizing or one can write which custom resizeStop handler which resizes columns in the table added by titleText option of setGroupHeaders.

All what I described above sound theoretical. So I wrote the small demo which demonstrates the approach. It displays the following grid

enter image description here

The demo is written not for the common case, but it's clear that one can use it as basis to more common solution. In any way I hope that you can change it to any your multi-level grid.

The most important parts of the demo you will find below:

var grid = $("#list"),
    setHeaderWidth = function () {
        var $self = $(this),
            colModel = $self.jqGrid("getGridParam", "colModel"),
            cmByName = {},
            ths = this.grid.headers, // array with column headers
            cm,
            i,
            l = colModel.length;

        // save width of every column header in cmByName map
        // to make easy access there by name
        for (i = 0; i < l; i++) {
            cm = colModel[i];
            cmByName[cm.name] = $(ths[i].el).outerWidth();
        }
        // resize headers of additional columns based on the size of
        // the columns below the header
        $("#h1").width(cmByName.amount + cmByName.tax + cmByName.total - 1);
        $("#h2").width(cmByName.closed + cmByName.ship_via - 1);
    };

grid.jqGrid({
    ...
    colModel: [
        {name: "id", width: 65, align: "center", sorttype: "int", hidden: true},
        {name: "invdate", width: 80, align: "center", sorttype: "date",
            formatter: "date", formatoptions: {newformat: "d-M-Y"}, datefmt: "d-M-Y"},
        {name: "name", width: 70},
        {name: "amount", width: 75, formatter: "number", sorttype: "number", align: "right"},
        {name: "tax", width: 55, formatter: "number", sorttype: "number", align: "right"},
        {name: "total", width: 65, formatter: "number", sorttype: "number", align: "right"},
        {name: "closed", width: 75, align: "center", formatter: "checkbox",
            edittype: "checkbox", editoptions: {value: "Yes:No", defaultValue: "Yes"}},
        {name: "ship_via", width: 100, align: "center", formatter: "select",
            edittype: "select", editoptions: {value: "FE:FedEx;TN:TNT;IN:Intim", defaultValue: "IN"}},
        {name: "note", width: 70, sortable: false}
    ],
    resizeStop: function () {
        // see https://mcmap.net/q/430482/-jqgrid-resize-grid-width-after-column-resized
        var $self = $(this),
            shrinkToFit = $self.jqGrid("getGridParam", "shrinkToFit");

        $self.jqGrid("setGridWidth", this.grid.newWidth, shrinkToFit);
        setHeaderWidth.call(this);
    }
});
grid.jqGrid ("navGrid", "#pager",
             {edit: false, add: false, del: false, refresh: true, view: false},
             {}, {}, {}, {multipleSearch: true, overlay: false});
grid.jqGrid("setGroupHeaders", {
    useColSpanStyle: true,
    groupHeaders: [{
        startColumnName: "amount",
        numberOfColumns: 5,
        titleText:
            '<table style="width:100%;border-spacing:0px;">' +
            '<tr><td id="h0" colspan="2"><em>Details</em></td></tr>' +
            '<tr>' +
                '<td id="h1">Price</td>' +
                '<td id="h2">Shiping</td>' +
            '</tr>' +
            '</table>'
    }]
});
$("th[title=DetailsPriceShiping]").removeAttr("title");
$("#h0").css({
    borderBottomWidth: "1px",
    borderBottomColor: "#c5dbec", // the color from jQuery UI which you use
    borderBottomStyle: "solid",
    padding: "4px 0 6px 0"
});
$("#h1").css({
    borderRightWidth: "1px",
    borderRightColor: "#c5dbec", // the color from jQuery UI which you use
    borderRightStyle: "solid",
    padding: "4px 0 4px 0"
});
$("#h2").css({
    padding: "4px 0 4px 0"
});
setHeaderWidth.call(grid[0]);

UPDATED: More later code of setGroupHeaders allows multiple calls of setGroupHeaders on the same grid. In the way one can do create multi-level headers. jqPivot uses the feature (see the wiki).

Amoretto answered 24/9, 2013 at 20:43 Comment(4)
Thanks for the response, so far it is working great. The one problem I've run into is when I freeze a column, the headers revert to a rowspan of 2, rather than the three in the demo. I'm looking into it, but any insight you may have would be great.Vexation
@ThomasMondelli: You are welcome! Could you describe the problem which you have more detailed. I didn't understood it from your last comment. Is the problem exist in the demo which I posted? What is the test case to reproduce the problem?Amoretto
I added frozen: true to the first two columns in the colModel to freeze them when the user scrolls horizontally. When the columns freeze, the height of the column header changes in the frozen columns.Vexation
@ThomasMondelli: It seems that you used frozen columns in not full correct way. Frozen columns have some problems and you have to do some additional work to fix it. Look at the answers and this one. If you would use fixPositionsOfFrozenDivs which I suggested before then the code will be something like here.Amoretto

© 2022 - 2024 — McMap. All rights reserved.