The normal way of handling onclick in d3 is
selection.append(element) .on("click", someFunction)
If I do it this way on 1000 svg elements, does it mean I just attached 1000 different listeners. If this is the case, is there event delegation for d3 specifically?
Advertisement
Answer
@AlexW answer is (partially) correct: there is no event delegation in D3, only event binding.
However, I said partially because it’d be better saying that “there is no native method for event delegation in D3″, since in fact it’s quite ease to implement it: the ugly alternative to do event delegation with D3 consists in using d3.event.target.
For instance, in this very simple demo, we bind this data…
var data = ["foo", "bar", "baz"];
… to the circles inside an <g>
element. Then, we bind an event listener to the group, and get the datum of each circle on click:
g.on("click", function() { console.log(d3.select(d3.event.target).datum()) })
Here is it:
var svg = d3.select("svg"); var g = svg.append("g"); var data = ["foo", "bar", "baz"]; var circles = g.selectAll(null) .data(data) .enter() .append("circle") .attr("cy", 40) .attr("cx", function(_, i) { return 50 + 100 * i }) .attr("r", 20) .attr("fill", "teal"); g.on("click", function() { console.log(d3.select(d3.event.target).datum()) })
<script src="https://d3js.org/d3.v4.min.js"></script> <svg></svg>
The nice thing about this approach is that, just as a jQuery event delegation, it works with elements created after the listener was defined. In the following demo, the red circle:
var svg = d3.select("svg"); var g = svg.append("g"); var data = ["foo", "bar", "baz"]; var circles = g.selectAll(null) .data(data) .enter() .append("circle") .attr("cy", 40) .attr("cx", function(_, i) { return 50 + 75 * i }) .attr("r", 20) .attr("fill", "teal"); g.on("click", function() { console.log(d3.select(d3.event.target).datum()) }); g.append("circle") .attr("cy", 40) .attr("cx", 275) .attr("r", 20) .attr("fill", "firebrick") .datum("foobar")
<script src="https://d3js.org/d3.v4.min.js"></script> <svg></svg>
So, despite D3 not having a native, explicit method for event delegation, the solution is quite simple and straightforward.