I am trying to get a nodes' bound datum with selection.on()
in D3 v6. In my event listener I'm getting the mouse event data instead of the datum. How do I get the datum?
This my code
const data = { "nodes": [{ "id": "Myriel", "group": 1 }, { "id": "Napoleon", "group": 1 }]}; const nodes = data.nodes.map(d => Object.create(d)); const node = svg.append("g") .selectAll("circle") .data(nodes) .join("circle") ... node.on("mouseover",d=>{ console.log(d); //output = MouseEvent console.log(d.id); //output = undefined });
D3v5 and earlier
In d3v5 and earlier we could use the pattern:
selection.on("eventType", function(d,i,nodes) { .... })
Where d
is the datum of the element triggering the event, i
is its index, and nodes
the current group of elements. Event information could be accessed within the event listener with d3.event
.
D3v6
In d3v6 the pattern has been changed:
selection.on("eventType", function(event, d) { .... })
Now the event is passed directly to the listener as the first parameter, the datum is now the 2nd parameter passed to the listener. As part of this change d3.event
has been removed.
As stated in the documentation:
D3 now passes events directly to listeners, replacing the d3.event global and bringing D3 inline with vanilla JavaScript and most other frameworks. (source)
This change applies to brush.on
, transition.on
, and drag.on
, zoom.on
as well as selection.on
.
this
You can still use d3.select(this)
in the event listener function as you did prior to d3v6. However, if using arrow functions, this
will have a different scope. In d3v5 and earlier you could use:
(d,i,nodes) => d3.select(nodes[i])...
In d3v6+ you can use (for selection.on()
):
(event,d) => d3.select(event.currentTarget)...
Positioning
To get the x,y position of the triggering event, where you would have used d3.mouse(this)
, you can now use:
d3.pointer(event);
Where you would have used d3.event.x
and d3.event.y
, in d3v5, you would now use:
event.x, event.y
Example
Below is a simple example of passing the event and the datum to the listener function in D3v6. The snippet uses d3.pointer() to get the x,y properties of the click relative to the SVG. Click on a rectangle to get the rectangle's datum and the x and y properties of the event logged to console:
var svg = d3.select("body") .append("svg"); svg.selectAll("rect") .data([1,2,3]) .enter() .append("rect") .attr("width",30) .attr("height",30) .attr("x", function(d) { return d*50; }) .on("click", function(event, d) { console.log(d); console.log(d3.pointer(event)); })
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/6.0.0/d3.min.js"></script>
What about i
and nodes
?
The index and the group of nodes are no longer passed to the event listener function. However, the migration guide does provide examples of how to find the current group of nodes and the index here.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With