Skip to content
Advertisement

Creating a table with D3

I’m trying to create a table in D3 that updates with new data. This mostly works.

Somehow I’m not getting any columns in newly added rows (so initially the table is empty).

What am I doing wrong?

See: https://jsfiddle.net/yev4kujn/21/

  var rows = tableBody.selectAll("tr").data(data);
  rows.exit().remove();
  rows.enter().append("tr");

  var cells = rows.selectAll("td")
    .data(function(d, i) {
      return Object.values(d);
    });
  cells.exit().remove();
  cells.enter().append("td")
    .text(function(d) {
      return d;
    });
    cells.text(function(d) {
      return d;
    });

Advertisement

Answer

In D3 selections are immutable. Therefore, when you do this…

rows.enter().append("tr")

… you are not changing what rows is: it keeps being an update selection, which is empty when the function runs for the first time. So, when you come to…

var cells = rows.selectAll("td")

… there are no <tr>s to append the <td>s.

All that being said, you have to change what rows is:

rows = rows.enter().append("tr").merge(rows);

Now rows contains the entered elements.

Here is your code with that change:

var data1 = [{
    "name": "Steve",
    "age": "34"
  },
  {
    "name": "Brian",
    "age": "44"
  },
  {
    "name": "Amy",
    "age": "45"
  }
];

var data2 = [{
    "name": "Jennifer",
    "age": "54",
    "adult": "no"
  },
  {
    "name": "Mike",
    "age": "14",
    "flowers": "yes"
  }
];

var toggle = true;

function update() {
  if (toggle) {
    updateTable(data1);
  } else {
    updateTable(data2);
  }
  toggle = !toggle;
}


var tableBody = d3.select("#tableBody");
update();

function updateTable(data) {

  var rows = tableBody.selectAll("tr").data(data);
  rows.exit().remove();
  rows = rows.enter().append("tr").merge(rows);

  var cells = rows.selectAll("td")
    .data(function(d, i) {
      return Object.values(d);
    });
  cells.exit().remove();
  cells.enter().append("td")
    .text(function(d) {
      return d;
    });
  cells.text(function(d) {
    return d;
  });
}
td {
  border: 2px solid green;
}

th {
  border: 2px solid red;
}

tr {
  border: 2px solid blue;
  display: block;
  padding: 3px;
  margin: 2px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<p>
  This button toggles between two datasets:
</p>
<button onclick="update()">
Toggle
</button>

<table>
  <thead>
    <tr>
      <th>Col 1</th>
      <th>Col 2</th>
      <th>Col 3</th>
    </tr>
  </thead>
  <tbody id="tableBody">
  </tbody>
</table>
Advertisement