Using d3 v3 to set and use .datum() on elements
With d3 v3, when you set .datum() on an element created from blah.selectAll(“blahblah”).enter(),
the datum is bound to the element, and can be used later.
With d3 v4, when you set .datum() on an element created from blah.selectAll(“blahblah”).enter(),
the element is bound to the .data() of the .enter(), and any .datum() you set cannot be used later,
unless you create a new selection that’s not bound to the data.
Compare this example to d3 v4 set datum.
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>d3 v3 set datum</title>
<!-- https://gist.github.com/kenpenn/c13d62dd437b5eb8bd76df9828adc3db -->
<style>
* { box-sizing: border-box; }
body {
font-size: 16px;
font-family: sans-serif;
margin: 0;
}
.btn { cursor: pointer; }
</style>
</head>
<body>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.17/d3.min.js"></script>
<script>
var width = 960;
var height = 500;
var svg = d3.select('body').append('svg').attr('width', width).attr('height', height);
var btnSwitch = svg.append('g').attr('class', 'btn').attr('transform', 'translate(10,10)');
var btnSwitchBg = btnSwitch.append('rect')
.attr('width', 186).attr('height', 44).attr('rx', 3).attr('ry', 3).attr('fill', '#eee').attr('stroke', '#ddd');
var btnSwitchTxt = btnSwitch.append('text').attr('x', 93).attr('y', 26).attr('text-anchor', 'middle');
btnSwitchTxt.text('click to switch colors');
var colors = ['hsl(341, 100%, 50%)', 'hsl(127, 100%, 50%)', 'hsl(242, 100%, 50%)'];
var circleG = svg.append('g').attr('transform', 'translate(0,64)');
var slots = colors.length + 1;
var spacing = width / slots;
var rad = 100;
var circles = circleG.selectAll('circle')
.data(colors);
circles.enter()
.append('circle')
.attr('cx', function(d,i) { return (i + 1) * spacing })
.attr('cy', rad)
.attr('r', rad)
.attr('fill', function(d) { return d })
.datum(function (d, i) { return { color: d, idx: i }; } );
btnSwitch.on('click', function () {
circles.each(function () {
nextColor(d3.select(this));
});
});
function nextColor (circle) {
var nextIdx = circle.datum().idx + 1 >= colors.length ? 0: circle.datum().idx + 1;
var next = this.colors[nextIdx];
circle
.attr('fill', next)
.datum({ color: next, idx: nextIdx });
}
</script>
</body>
</html>