I love the DC.JS library and have been trying to create a clickable aggregated table in DC.js with partial success. I want to highlight the rows on click event(multiple selections allowed) similar to the row chart or an ordinal bar chart in dc js. Like a row chart, when multiple selections are made, multiple table rows should be highlighted.
I am not able to select the row that I have clicked on, rather, my css selects the first row irrespective of which row I click. I tried to use 'this' keyword to select the current row that was clicked but to no avail.
Here's the js fiddle: https://jsfiddle.net/yashnigam/kvt9xnbs/83/
Here's my code for the click event that makes the css selection:
marketTable.on("renderlet", function(chart){
chart.selectAll('tr.dc-table-row').on('click',function(d){
if(filterKeys.includes(d.key)){
chart.select('tr.dc-table-row').datum(d.key).style('background-color','gray');
}
})
});
Kindly share a way to highlight rows of data table on click, the same way it works on a row chart.
@Hassan has the right idea. I would suggest selecting the tr
s rather than the td
s, and instead of changing the classes on click (which wouldn't survive a redraw), apply the classes also during the pretransition
event.
So:
tr.dc-table-row.sel-rows {
background-color: lightblue;
}
marketTable.on('pretransition', function (table) {
table.selectAll('td.dc-table-column')
.on('click', /* ... */)
table.selectAll('tr.dc-table-row')
.classed('sel-rows', d => filterKeys.indexOf(d.key) !== -1)
});
We apply the class based on whether the row's key is in the array. Straightforward and simple!
Fork of your fiddle.
@vbernal pointed out that the list doesn't get reset when you click the reset link. To better integrate this, we can hook into the built-in filters that the table inherits from the base mixin (but doesn't ordinarily use):
marketTable.on('pretransition', function (table) {
table.selectAll('td.dc-table-column')
.on('click',function(d){
let filters = table.filters().slice();
if(filters.indexOf(d.key)===-1)
filters.push(d.key);
else
filters = filters.filter(k => k != d.key);
table.replaceFilter([filters]);
dc.redrawAll();
});
let filters = table.filters();
table.selectAll('tr.dc-table-row')
.classed('sel-rows', d => filters.indexOf(d.key) !== -1);
});
Instead of setting dimension.filter()
ourselves, we fetch the existing table.filters()
, toggle as needed, and then set the filters using
table.replaceFilter([filters])
(Note the extra brackets.)
When the reset link is clicked, we reset the filter on the table rather than the crossfilter dimension. (It's always better to manipulate filters through the chart, because charts are not able to read the selection state from the crossfilter dimension.)
$('#resetTable').on('click', function() {
marketTable.filter(null);
dc.redrawAll();
});
New version of fiddle.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With