Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 504
justinlav Avatar asked Sep 25 '17 21:09

justinlav


2 Answers

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.

like image 112
Martin Wickman Avatar answered Sep 29 '22 07:09

Martin Wickman


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);
},
like image 40
ZooZ Avatar answered Sep 29 '22 08:09

ZooZ