2
votes

I've set up a small dc.js dashboard with a pie chart representing different experiments to select, a series chart representing the experiment results, and associated range chart for the results. The range chart correctly updates the series chart and similarly, the pie chart correctly updates the series chart. However, the range chart and the pie chart don't seem to want to play nice with one another. When I set filter the range in the range chart, the pie chart goes empty.

enter image description here

I've made a jsfiddle here: https://jsfiddle.net/nwhite/zb1xf0cu/132/

Ideally, I could select 2 or so experiments with the pie chart and then use the range chart to zoom in on areas of interest. But when I apply the range filter, the pie chart disappears.

Both the series chart and range chart use the same dimension (runDimension) and group (runGroup), while the pie chart uses exptDimension and exptGroup:

ndx = crossfilter(experiments);
runDimension = ndx.dimension(function(d) {return [+d.Expt, +d.Run]; });
runGroup = runDimension.group().reduceSum(function(d) { return +d.Speed; });

exptDimension = ndx.dimension(function(d) {return +d.Expt; });
exptGroup = exptDimension.group();
1

1 Answers

1
votes

Although it was introduced a few years ago, the seriesChart is still bleeding edge and some features don't work correctly.

The issue is that the dimension key ([+d.Expt, +d.Run]) does not agree with the filters that the chart applies, which are RangeFilters over d.Run only.

(Here's the issue on GitHub.)

It's not as efficient as a real RangedFilter but we can define a filter handler that peers into the composite keys used by this dimension, and checks whether the second part (via the keyAccessor) is within the range:

function seriesFilter(dimensions, filters) {
  if (filters.length === 0) {
    runDimension.filter(null);
  } else {
    var filter = dc.filters.RangedFilter(filters[0][0], filters[0][1]);
    runDimension.filterFunction(function(k) {
      return filter.isFiltered(rangeChart.keyAccessor()({key: k, value: null}));
    });
  }
  return filters;
}

Compounding the problem, a composite chart will apply its filters not just at the parent level but within each child. So we need to patch quite a few filterHandlers in order to get this to work.

We have to apply this filterHandler to the focus chart, range chart, and all of their children too!

rangeChart.filterHandler(seriesFilter);
seriesChart.filterHandler(seriesFilter);
rangeChart
    // ...
    .chart(function(c) { return dc.lineChart(c).curve(d3.curveCardinal).filterHandler(seriesFilter); })
// same with seriesChart

Working fork of your fiddle.

Note that no matter what you select, the slices will always be the same size. So the only cool thing in the demo is the pie chart not going blank when you select something.