Reputation: 4506
I'm currently learning D3 and had a question relating to interactivity.
The following example works to resize a group of circles on-screen based on the button clicked. It works (I am following a tutorial). Essentially, key names from a CSV file are bound to each button, which when clicked, relays that key name to an attached function (named buttonClick in this example) which is used to access the values for that key/value pair in each object of my data. The d3.max() function then is used to calculate the max value, which is used to determine a new scale and redraw the circles accordingly.
My question is: How does the function buttonClick know to accept the "data" attribute bound to each button as an argument? Why are there no parentheses for the function when it is called inside the onclick event handler?
Thanks for any help you can provide.
function createSoccerViz() {
d3.csv("worldcup.csv", data => {overallTeamViz(data)
});
function overallTeamViz(incomingData) {
d3.select("svg")
.append("g")
.attr("id","teamsG")
.attr("transform", "translate(50,300)")
.selectAll("g").data(incomingData).enter()
.append("g")
.attr("class", "overallG")
.attr("transform", (d,i) => "translate(" + i * 60 + "," + 0 +")");
var teamG = d3.selectAll("g.overallG")
teamG.append("circle")
.attr("r",20)
teamG.append("text")
.text(d => d.team)
.attr("y", 30)
dataKeys = Object.keys(incomingData[0])
.filter(d => d !== "team" && d !== "region")
d3.select("#controls").selectAll("button.teams")
.data(dataKeys).enter()
.append("button")
.html(d => d)
.on("click", buttonClick) ////// Why no parentheses here?
function buttonClick(datapoint) {
var maxValue = d3.max(incomingData, d => parseFloat(d[datapoint]))
var radiusScale = d3.scaleLinear().domain([0, maxValue]).range([2,20])
d3.selectAll("g.overallG").select("circle")
.attr("r", d => radiusScale(d[datapoint]))
}
Upvotes: 5
Views: 12257
Reputation: 102218
You have two questions here:
Regarding the parenthesis, if you had them...
.on("click", buttonClick())
... you'd be passing the result of the function to the event listener (in your case, undefined
), and that's not what you want.
Instead, you want the function to be called when you click the button, hence:
.on("click", buttonClick)
Or, alternatively:
.on("click", function(){
buttonClick()
})
Regarding the first argument the API is clear:
When a specified event is dispatched on a selected element, the specified listener will be evaluated for the element, being passed the current datum (d), the current index (i), and the current group (nodes), with this as the current DOM element (nodes[i]). (emphasis mine)
Therefore, you don't need to explicitly specify the first argument: it will be the datum by default.
Upvotes: 7