dc.js add multiple filters at once

2019-07-30 15:37发布

Is it possible to add a set of filters at once on a dc chart? For instance, say I have a pieChart, and an array of filter values to apply.

var osChart = dc.pieChart('#oschart');

And an input set of filters, say

var filters = ["linux", "mac osx", "windows", "solaris"]

How can I apply filters so that only one "filtered" event is generated? I can do something like

for (var i=0; i < filters.length; i++) {
  osChart.filter(filters[i]);
}

However that would generate 4 filtered event. I am applying filters based on what a user typed on a text box. When a filter is applied, I am making some ajax calls, and this tends to slow down if I apply filters one by one. I can avoid extra ajax calls if the filters can be set at once.

crossfilter has a function filterFunction which can get this task done, but I am not sure how I can apply that on a dc chart. Apply filterFunction on osChart.dimension() did not work. With the latest dc release, I saw some functions like addFilterHandler and removeFilterHandler however I cannot test and deploy that version right now.

What other options do I have?

标签: dc.js
1条回答
孤傲高冷的网名
2楼-- · 2019-07-30 16:42

From looking at the code, which is somewhat convoluted, you can pass the array inside another array to .filter() (or the undocumented but unmagical .replaceFilter()) without a performance penalty, because it will apply all of the filters before invoking the filtered event.

From the latest .filter() source, which uses handlers but has the same behavior:

    if (_ instanceof Array && _[0] instanceof Array && !_.isFiltered) {
        _[0].forEach(function (d) {
            if (_chart.hasFilter(d)) {
                _removeFilterHandler(_filters, d);
            } else {
                _addFilterHandler(_filters, d);
            }
        });
    } else if (_ === null) {
        _filters = _resetFilterHandler(_filters);
    } else {
        if (_chart.hasFilter(_)) {
            _removeFilterHandler(_filters, _);
        } else {
            _addFilterHandler(_filters, _);
        }
    }
    applyFilters();
    _chart._invokeFilteredListener(_);

So if it finds an array that does not have an isFiltered method, and that array's first element is also an array, it will iterate over the elements in the nested array.

For example, pass [["linux", "mac osx", "windows", "solaris"]] to filter on those four values. (Thanks @marcin for clarifying!)

查看更多
登录 后发表回答