Search code examples
d3.jsdc.jscrossfilterreductio

Remove empty groups from dc.js graph


I have gone through all the SO questions on removing empty bins from a dc.js graph but couldn't find anything besides the fake group approach

filter_group = function(oldGroup) {
    return {
        all: oldGroup.all().filter(...)
    };
}
newGroup = filter_group(oldGroup);

and then use newGroup in the dc.js graphs.

What this does for me is create the right set of bins on first draw but it doesn't re-filter when I apply filters to other dimensions. So I end up with the correct intial bins but in subsequent redraws I still end up with empty bins.

What I would like to achieve is proper re-filter and redraw i.e getting rid of the bins according to my filter function and redraw excluding the filtered bins so having a varying number of bins.

Here is a fiddle that shows what I mean. I have set up the data so that filtering on a in the first graph should remove the g bar in the second (and filtering on g in the second should remove the a one in the first graph) But it doesn't remove the empty bar from the axis, it just shows the label with no bar.

Starting point : enter image description here

After filtering on g in second graph (I would like a to not even show on the axis) : enter image description here

PS : I have tagged reductio and d3.js in case there is an elegant solution using those packages even though I'd rather keep it within dc.js.


Solution

  • The X scale's domain determines which bars are shown.

    You are manually setting the domains on your charts:

    .x(d3.scale.ordinal().domain(filter_group(group).all().map(function(d) {return(d.key);}).unshift("")))
    

    I'm sure you were solving some other problem with that, but if you remove that, and specify

    .elasticX(true)
    

    instead, then you don't need the on("filtered",... and the charts will remove bins when their values are zero.

    Fork of your fiddle.