d3.js v4: How to access parent group's datum index?

前端 未结 8 735
萌比男神i
萌比男神i 2020-11-28 10:33

The description of the selection.data function includes an example with multiple groups (link) where a two-dimensional array is turned into an HTML table.

8条回答
  •  孤街浪徒
    2020-11-28 11:04

    If j is the nodeList...

    • j[i] is the current node (eg. the td element),
    • j[i].parentNode is the level-1 parent (eg. the row element),
    • j[i].parentNode.parentNode is the level-2 parent (eg. the table element),

    • j[i].parentNode.parentNode.childNodes is the array of level-1 parents (eg. array of row elements) including the original parent.

    So the question is, what is the index of the parent (the row) with respect to it's parent (the table)?

    We can find this using Array.prototype.indexOf like so...

    k = Array.prototype.indexOf.call(j[i].parentNode.parentNode.childNodes,j[i].parentNode);
    

    You can see in the snippet below that the row is printed in each td cell when k is returned.

    var testData = [
    [
      {x: 1, y: 1},
      {x: 1, y: 2},
      {x: 1, y: 3},
      {x: 1, y: 4}
    ], [
      {x: 2, y: 1},
      {x: 2, y: 2},
      {x: 2, y: 3},
      {x: 2, y: 4}
    ], [
      {x: 3, y: 4},
      {x: 3, y: 4},
      {x: 3, y: 4},
      {x: 3, y: 4}
     ]
    ];
    
    var tableData =
      d3.select('body').selectAll('table')
        .data([testData]);
    
    var tables =
      tableData.enter()
      .append('table');
    
    var rowData =
      tables.selectAll('table')
        .data(function(d,i,j){
          return d;
        });
    
    var rows =
      rowData.enter()
      .append('tr');
    
    var eleData =
      rows.selectAll('tr')
        .data(function(d,i,j){
          return d;
        });
    
    var ele =
      eleData.enter()
      .append('td')
        .text(function(d,i,j){
          var k = Array.prototype.indexOf.call(j[i].parentNode.parentNode.childNodes,j[i].parentNode);
          return k;
        });

    Reservations

    This approach is using DOM order as a proxy for data index. In many cases, I think this is a viable band-aid solution if this is no longer possible in D3 (as reported in this answer).

    Some extra effort in manipulating the DOM selection to match data might be needed. As an example, filtering j[i].parentNode.parentNode.childNodes for elements only in order to determine the row -- generally speaking the childNodes array may not match the selection and could contain extra elements/junk.

    While this is not a cure-all, I think it should work or could be made to work in most cases, presuming there is some logical connection between DOM and data that can be leveraged which allows you to use DOM child index as a proxy for data index.

提交回复
热议问题