idiomatic update of group elements
http://stackoverflow.com/questions/26310664/incorrect-svg-group-being-deleted#26422833
by Nivaldo
HTML
<div id="data-field"></div>
<button id="add-btn">Add Data</button>
<p>Click on a bar to remove it</p>
CSS
.chart rect {
fill: teal;
}
.chart text {
fill: white;
font: 30px sans-serif;
text-anchor: end;
}
JavaScript
var barHeight = 75, margin = 3, padding = 3, i=0;
var chartData = [6,12,15,21,29,41];
var chart = d3.select("body")
.append("svg")
.attr("class","chart")
.attr("width", 600)
.attr("height", 600);
drawChart();
function drawChart() {
var group = chart.selectAll("g")
.data(chartData);
// remove bars and labels associated to deleted data point
group.exit()
.remove();
// add group element
var groupEnter = group.enter()
.append("g");
// add rect to group element
groupEnter
.append("rect");
// add label to group element
groupEnter
.append("text");
// update transform and click event at the group level
// this way BOTH bars and labels are position correctly and
// BOTH will respond to click events
group
.attr("transform", function (d, i) { return "translate(0," + i * (barHeight + margin) + ")"; })
.on("click", function (d, i) {
// remove data point; no need to remove corresponding DOM element; this will be taken care off via group.exit()
chartData.splice(i, 1);
drawChart();
});
// update bars
group.select("rect")
.data(chartData) // update data bound to rects
.attr("width", function (d) { return d * 10 + "px"; })
.attr("height", barHeight);
// update labels
group.select("text")
.data(chartData) // update data bound to labels
.attr("x", function (d) { return d * 10 - padding + "px"; })
.attr("y", barHeight / 3 + padding + "px")
.text(function (d) { return d; });
// update list of numbers
d3.select("#data-field").text("numbers: [" + chartData.join(", ") + "]");
}
// add more data
d3.select("#add-btn")
.on("click", function(d) {
var datapt = (Math.round(Math.random() * 50) + 1);
console.log('new data point is',datapt);
chartData.push(datapt);
...