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>