简体   繁体   English

将d3与自定义的角度指令集成

[英]Integrating d3 with a custom angular directive

I am working on an application that uses angular to keep data coming in from a few different services in sync and to hand this data off to some d3 functions to generate graphics and tables. 我正在开发一个应用程序,该应用程序使用angular保持来自几个不同服务的数据同步,并将此数据传递给某些d3函数以生成图形和表格。

Right now, I'm having difficulty getting the data bound at the correct level within the d3 code. 现在,我很难在d3代码中以正确的级别绑定数据。 I'm creating a basic table at this point. 此时我正在创建一个基本表。

Here is my directive: 这是我的指令:

application.directive('d3table', function() {
   var chart = table();
   return  {
       restrict: 'E',
       scope: {
        data: "="
       },
       link: function(scope, element, attrs) {
           scope.$watchCollection('data', function(data) {
               d3.select(element[0]).datum(data).call(chart);
           });
       }
   }
});

My d3 code for table() is as follows, using the toward reusable charts approach: 我的table()的d3代码如下,使用了朝可重用图表的方法:

function tableChart() {
    function chart(selection) {
        selection.each(function(dataset) {
            var table = d3.select(this).append('table');

            table.append('thead').append('tr')
              .selectAll('tr').data(columns).enter()
              .append('th').text(function(d) { return d;});
    }
    return chart;
}

The data I am working here is a simple array. 我在这里工作的数据是一个简单的数组。 Data is added and removed periodically. 定期添加和删除数据。

The issue I am having is that instead of updating the existing table, the appending of data is triggering the generation of a new table. 我遇到的问题是,添加数据而不是更新现有表,而是触发了新表的生成。 So I end up with multiple tables, instead of one which is properly bound to the d3 function. 因此,我最终得到多个表,而不是正确绑定到d3函数的表。

You could remove the table beforehand. 您可以事先删除表格。

function tableChart() {
    function chart(selection) {
        selection.each(function(dataset) {
            //remove existing table
            d3.select(this).select("table").remove();

            var table = d3.select(this).append('table');

            table.append('thead').append('tr')
              .selectAll('tr').data(columns).enter()
              .append('th').text(function(d) { return d;});
    }
    return chart;
}

I Would use a template and just basically have your table and table head info in there then in the link function you can get a reference to the table. 我将使用一个模板,基本上只在其中包含您的表和表头信息,然后在链接函数中可以获取对该表的引用。 Then in the watch collection function your only adding or removing rows, not trying to recreate the whole table each time. 然后在watch collection函数中,您仅添加或删除行,而不是每次都尝试重新创建整个表。 This approach will work as long as your data scheme stays the same. 只要您的数据方案保持不变,这种方法就可以工作。

Here is some code to look at 这是一些代码要看

//js
var app = angular.module('plunker', []);

app.controller('MainCtrl', function($scope) {
  $scope.name = 'D3 Angular Table';

  $scope.data = [1,2,3,4,5,6,7,8];


  $scope.add = function(){
    console.log('add');
    $scope.data.push(Math.floor(Math.random() * 100) );
  };

   $scope.remove = function(){
    console.log("remove")
     $scope.data.splice(0, 1)
  };
});




app.directive('d3table', function() {
   //var chart = table();
   return  {
       restrict: 'E',
       scope: {
        data: "="
       },
      templateUrl: 'd3table.html',
       link: function(scope, element, attrs) {

           var table = element[0].firstChild;

           scope.$watchCollection('data', function(data) {

             var selectedTable = d3.select(table).selectAll('tr').data(data);

              selectedTable.enter()
              .append("tr")
              .text(function(d){return d});

              selectedTable.exit().remove();

           });
       }
   }
});
//html
<table id = "test" >
  <thead>
     <tr><th>Value</th></tr>
  </thead>
</table>

working plunk 工作勤奋

http://plnkr.co/edit/hb6t9gshXBngApUGyJkN?p=preview http://plnkr.co/edit/hb6t9gshXBngApUGyJkN?p=预览

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM