justinlav
justinlav

Reputation: 155

jQuery Datatables rowGroup Collapse/Expand

I'm using jQuery Datatables and I would like to incorporate row grouping into the table.

I have attempted to incorporate it myself by adding rows and a click event handler to expand/collapse the rows pertaining to that row group. This relies on toggling the visibility of the rows, which works but is messy.

I had an issue here with large tables where most rows aren't in the DOM until a scroll event calls drawCallback, so when I gave rows a certain class to associate them with a row group, the classes were removed on every scroll of the table.

Datatables recommends using their rowGroup extension which I have currently incorporated into my table. https://datatables.net/extensions/rowgroup/

This extension has no option to expand or collapse a group, does anyone have any experience manipulating this extension to add expand/collapse functionality?

I have attempted to override $.fn.dataTable.ext.search.push to simulate a "filter" that won't draw certain rows, which I can do. The issue here is that I can't decide which row is a rowGroup row in this method to draw so all of the rowGroup rows are removed.

Has anyone had any luck expanding/collapsing groups using the rowGroup extension?

Upvotes: 9

Views: 29753

Answers (4)

MomasVII
MomasVII

Reputation: 5081

My quick and dirty solution is this...

$('.group').click(function() {
    //$(this+" .group_date .date_arrow").addClass("rotateSVG");
    var nextItem = $(this).next('tr');
    while(nextItem.attr('class') != 'group') {
        nextItem.fadeToggle();
        if(nextItem.next('tr').length == 0) {
            break;
        }
        nextItem = nextItem.next('tr');
    }
});

Upvotes: 0

Martin Wickman
Martin Wickman

Reputation: 19925

First add a state to keep track of collapsed groups:

 var collapsedGroups = {};

Next, add this to the Datatable initialization to enable the rowGroup plugin. It works by checking collapapsedGroups and then this info to hide or show the rows. It also adds a css-class indicating if it's collapsed or not:

 {
    rowGroup: {
        // Uses the 'row group' plugin
        dataSrc: 'product.category',
        startRender: function (rows, group) {
            var collapsed = !!collapsedGroups[group];

            rows.nodes().each(function (r) {
                r.style.display = collapsed ? 'none' : '';
            });    

            // Add category name to the <tr>. NOTE: Hardcoded colspan
            return $('<tr/>')
                .append('<td colspan="8">' + group + ' (' + rows.count() + ')</td>')
                .attr('data-name', group)
                .toggleClass('collapsed', collapsed);
        }
  }

Finally, add a handler for clicking on the row for collapsing/expanding rows. This causes a redraw of the table which, in turn, calls startRender above:

   $tbody.on('click', 'tr.group-start', function () {
        var name = $(this).data('name');
        collapsedGroups[name] = !collapsedGroups[name];
        table.draw();
    });

Here is a working example.

Upvotes: 23

ZooZ
ZooZ

Reputation: 971

You can also add a toggler icon to indicate collapse state (using font awesome):

startRender: function (rows, group) {
    var collapsed = !!collapsedGroups[group];

    rows.nodes().each(function (r) {
        r.style.display = collapsed ? 'none' : '';
    });

    var toggleClass = collapsed ? 'fa-plus-square' : 'fa-minus-square';

    // Add group name to <tr>
    return $('<tr/>')
        .append('<td colspan="' + rows.columns()[0].length +'">' + '<span class="fa fa-fw ' + toggleClass + ' toggler"/> ' + group + ' (' + rows.count() + ')</td>')
        .attr('data-name', group)
        .toggleClass('collapsed', collapsed);
},

Upvotes: 8

justinlav
justinlav

Reputation: 155

I have found my own answer so I want to share it if anyone else has future problems with this.

Use the below code to implement row Grouping where index is the column index that you want to group by:

var dataSrc = g_oTable.columns(index).dataSrc();

g_oTable.order([index, "asc"]).draw();
g_oTable.order.fixed({
    pre: [ index, 'asc' ]
}).draw();

g_oTable.rowGroup().dataSrc(dataSrc[0]);
g_oTable.rowGroup().enable().draw();

$('.group').each(function(i, obj) {
    $(obj).nextUntil('tr.group').each(function(i) {
        $(this).toggle();
    });
});
g_oTable.draw();

Then add a click event handler to your row Groups:

$( document ).on("click", "tr.group", function(){
    $(this).nextUntil('tr.group').toggle();
});

Upvotes: 0

Related Questions