Reputation: 155
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
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
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
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
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