带有dc.js的crossfilter.js更新了回调组更改的图表

时间:2017-04-19 11:38:56

标签: javascript angular d3.js dc.js

我有一个工厂用于创建dc.js图表​​,它使用绑定到$ scope的crossfilters函数。 Plnkr Example

$scope.updateMyPie = function(data) {
     var cf = crossfilter(data)
     $scope.mypie.dimension = cf.dimension(function(d) { return d.key })
     $scope.mypie.group = 
     $scope.mypie.dimension.group().reduceSum(function(d){ return d.value });
}

图表工厂通过角度指令通过DOM获取所有图表属性,因此标签就像这样

<mypie id="mypie" chart-dimesion="mypie.dimension" chart-group="mypie.group"...etc

这种方法适用于过滤,初始数据加载,绑定和图表渲染等等。但这是一个例外。如果我有类似按钮点击事件触发新数据请求,然后我使用上面作为回调它采取并处理数据罚款,但不更新图表。即使我包含dc.redrawAll()或renderAll()等等。

我尝试嵌入redraw(),redrawAll(),验证数据是否正确返回,完全销毁标记并重新创建并附加到DOM等。我的假设是我使用这种工厂式创建DC / D3图表的实现存在问题,但我认为如果我更新了范围内的组和/或尺寸,它应该仍然有用吗?似乎图表对象没有获取对dim / groups的更改?我可以通过在初始调用和第二次调用中使用以下内容来验证$ scope.etc引用的cf组值是否已更改:

var print_filter = function(filter) {
    var f = eval(filter);
    if (typeof (f.top) != "undefined") { 
        f = f.top(Infinity);
    }
    if (typeof (f.dimension) != "undefined") { 
        f = f.dimension(function (d) { 
            return ""; 
        }).top(Infinity);
    }

    console.log(filter + "(" + f.length + ") = " + JSON.stringify(f).replace("[", "[\n\t").replace(/}\,/g, "},\n\t").replace("]", "\n]"));
};

更新:添加了plnkr,并试图更好地解释=所以在这个例子中,我有一种“传统”方式来构建dc图表,而不是我试图使用指令和元素实现的基于服务的方法。一切都有效,除了我试图在plnkr中展示的......当我请求新数据(ajax)时,第一次更新很好,基于指令的方法似乎没有任何效果。我尝试了很多方法,但基本上更新$ scope dim / group应该正常工作?我认为它是双向绑定因此这些“两个范围”应该共享参考?但即使我使用范围。$ parent.my.dimension等也不会影响它。

1 个答案:

答案 0 :(得分:1)

您的图表仍然绑定到旧的交叉过滤器,维度和组。通常,在加载新数据或替换数据时,请不要丢弃交叉过滤器,维度或组。使用crossfilter.removecrossfilter.add方法添加或删除数据。

以下是修改示例的方法:

在创建控制器时预先创建Crossfilter,尺寸和组,然后在将来不再创建或销毁它们:

myapp.controller('mycontroller', ['$scope', 'dataCaller', function($scope, dataCaller){
      $scope.pageTitle = "Updating DC.js and Crossfilter";

      $scope.currentData1 = "data1.json";
      $scope.currentData2 = "data1.json";

      $scope.my = {};
      $scope.my.cf = crossfilter();
      $scope.my.dimension = $scope.my.cf.dimension(function(d){ return d.key; })
      $scope.my.group = $scope.my.dimension.group().reduceSum(function(d){ return d.value; })

然后更改您的更新功能,只需切换Crossfilter中的数据:

 $scope.factoryBuildPieExample = function(data) {
    $scope.my.cf.remove()
    $scope.my.cf.add(data.response.data)
    dc.redrawAll();
  }

如果您想在执行此操作时维护dc.js过滤器,此问题/答案将解释如何:Updating dc.js data and reapplying original filters

这是一个有效的Plunker:http://plnkr.co/edit/UbfKsuhg9vH678MR6fQT?p=preview