带有rowspan的D3表

时间:2015-10-07 17:52:59

标签: javascript d3.js

我是D3的重复新手,但尝试使用D3来转换它已经死路一条:

[
 { Year: 2014, Month: 'Dec', Team: 'T1', Sales: 123 },
 { Year: 2015, Month: 'Jan', Team: 'T1', Sales: 123 },
 { Year: 2015, Month: 'Jan', Team: 'T2"', Sales: 123 },
 { Year: 2015, Month: 'Feb', Team: 'T1', Sales: 123 },
 { Year: 2015, Month: 'Feb', Team: 'T2"', Sales: 123 },
 { Year: 2015, Month: 'Apr', Team: 'T1', Sales: 123 },
 { Year: 2015, Month: 'Apr', Team: 'T2"', Sales: 123 },
 { Year: 2015, Month: 'Mar', Team: 'T1', Sales: 123 },
 { Year: 2015, Month: 'Mar', Team: 'T2"', Sales: 123 }
]

进入这个:

<table border="1">
    <tr>
        <td>Year</td>
        <td>Month</td>
        <td>T1</td>
        <td>T2</td>
    </tr>
    <tr>
        <td rowspan="1">2015</td>
        <td>Dec</td>
        <td>123</td>
    </tr>
    <tr>
        <td rowspan="4">2015</td>
        <td>Jan</td>
        <td>123</td>
        <td>123</td>
    </tr>
    <tr>
        <td>Feb</td>
        <td>123</td>
        <td>123</td>
    </tr>
    <tr>
        <td>Apr</td>
        <td>123</td>
        <td>123</td>
    </tr>
    <tr>
        <td>Mar</td>
        <td>123</td>
        <td>123</td>
    </tr>
</table>

有可能吗?我尝试用nest预处理数据来重组它,但仍然无法获得我想要的表输出。

任何有关的提示或指示

2 个答案:

答案 0 :(得分:0)

我已经使用d3首先将所有数据转换为基于年份的嵌套格式:

var nested_data = d3.nest()
    .key(function (d) {
    return d.Year;
}).entries(data);

然后创建了这样的表格:

nested_data.forEach(function (d) {
    var rowspan = d.values.length;
    d.values.forEach(function (val, index) {
        var tr = thead.append("tr");
        if (index == 0) { //rowspan only for first element
            tr.append("td")
                .attr("rowspan", rowspan)
                .text(val.Year);
        }
        tr.append("td")
            .text(val.Month);
        tr.append("td")
            .text(val.Team);
        tr.append("td")
            .text(val.Sales);

    });
});

完整的工作代码here

希望这有帮助!

答案 1 :(得分:0)

我希望能够做到这一点,但需要能够保留d3数据绑定,以便我可以访问点击事件的数据。

通过允许d3通过selection.data(...)函数绑定数据,d3会跟踪哪些dom元素属于哪些基准。代码与@cyril基本相同,确实为每个循环使用a来创建元素;然而,这一切都是通过d3调用与普通javascript循环完成的,这些循环创建了一个静态显示。

另一个不同之处在于,我将全年的父集合分组到表中的tbody元素中。

JSBin上的工作示例。

var table = d3.select("body").append("table"),
  thead = table.append("thead");

thead.append("tr")
  .selectAll("th")
  .data(["Year", "Month", "T1", "Sales"])
  .enter()
  .append("th")
  .text(function(column) {
    return column;
  });

//this will group my data into key:year and all its yearly data
var nested_data = d3.nest()
  .key(function(d) {
    return d.Year;
  }).entries(data);

var rowgroups = table.selectAll('tbody')
  .data(nested_data)
  .enter()
  .append('tbody')
  .each(function(rowgroup) {
    var rowspan = rowgroup.values.length;
    // Add the actual table rows nested in a tbody for this group of year
    d3.select(this)
      .selectAll('tr')
      .data(function(d) {
        return d.values;
      })
      .enter().append('tr')
      .each(function(rowdata, index) {
        var row = d3.select(this);
        if (index == 0) {
          row.append('td').attr('rowspan', rowspan).text(rowdata.Year);
        }
        row.append('td').text(rowdata.Month);
        row.append('td').text(rowdata.Team);
        row.append('td').text(rowdata.Sales);

        // Add a click handler that will return the datum instead of undefined
        row.on('click', function(rowdata) {
          console.log('Row Clicked');
          console.log(rowdata);
        });
      });
  });

我是d3的新手并希望得到有关此解决方案的反馈,它确实可以确定这是否是最好的方法。