Reputation: 70122
I'm rendering a table of data using D3, and have successfully managed to make the initial render work:
var data = [
[1,2,3],
[1,2,3],
[1,2,3]
];
render(data);
function render(data) {
var container = d3.select('#container');
var table = container.select('table');
if (!table.node()) {
table = container.append('table')
.classed('legend', true);
}
// create the row selection
var tr = table.selectAll('tr')
.data(data);
// append 'tr' on enter
tr.enter()
.append('tr');
// create the cell selection
var td = tr.selectAll('td')
.data(function(d) { return d; });
// append on enter
td.enter()
.append('td');
// update cell text on update
td.text(function(d) {
return d;
});
}
The above code creates a table if one isn't presented (to avoid having a triple nested join!), it creates a datajoin for the rows, then a nested datajoin for the cells.
With the above code, the initial data renders just fine.
However, if I updated the data as follows:
setTimeout(function() {
for (var i = 0; i < 3; i++) {
for(var j = 0; j < 3; j++) {
data[i][j] = data[i][j] + Math.random();
}
}
render(data);
}, 500);
I would expect that the last statement which is the td update selection to be invoked each time:
td.text(function(d) {
return d;
});
Unfortunately, this is not the case!
I've seen examples that show enter / exit / update for simple datajoins (e.g http://bost.ocks.org/mike/join/), and also examples for nested datajoins.
However, I've not seen an example that demonstrates enter / exit / update for a nested datajoin. Can anyone see what is wrong with my above code and why the td update selection is not being called on subsequent 'render' steps?
JSBin: http://jsbin.com/xoqaxayamu/edit?html,output
Upvotes: 1
Views: 496
Reputation: 6476
To murder the metaphor even more, you shouldn't have to being doing a tap dance routine like this in d3...
var table = container.select('table');
if (!table.node()) {
table = container.append('table')
.classed('legend', true);
}
Here is the idiomatic way to do it...
var data = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9]
];
render(data);
render(data);
render(data);
function render(data) {
var container = d3.select('#container');
var table = container.selectAll('table')
.data([data]);
table.enter().append("table").classed("legend", true)
table.exit().remove();
// create the row selection
var tr = table.selectAll('tr')
.data(function(d) {
return d
});
tr.exit().remove();
// append 'tr' on enter
tr.enter()
.append('tr');
// create the cell selection
var td = tr.selectAll('td')
.data(function(d) {
return d;
});
td.exit().remove();
// append on enter
td.enter()
.append('td');
// update cell text on update
td.text(function(d) {
return d3.format(" >8,.3f")(d);
});
}
setInterval(function() {
for (var i = 0; i < 3; i++) {
for(var j = 0; j < 3; j++) {
data[i][j] = data[i][j] + Math.random();
}
}
render(data);
}, 500);
body {
white-space: pre;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<div id="container"></div>
Upvotes: 1