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>