Reputation: 12645
I'm drawing a set of circles on an SVG Container using d3.js.
I have an eventList
. For each element in this list, I draw a circle. Here is how I do it. It works:
var eventList = [
Object {stateId: 5},
Object {stateId: 6},
Object {stateId: 7},
];
for (var i = 0; i <= eventList.length-1; i++) {
var currEvent = eventList[i];
var myCircle = self.svgContainer.append("circle")
.attr("cx", i * 100)
.attr("cy", i * 100)
.attr("r", 5)
.attr("stroke-width", 0)
.attr("fill", "red");
}
I'm now trying to add on-click behavior to each of these circles. I want clicking on each circle to take me to a specific URL based on data found in the eventList. Here's what I'm adding into the loop above:
myCircle.on({
"click": function() {
console.log("Hello! currEvent.stateId=", currEvent.stateId.toString());
console.log("currEvent = ", currEvent);
$state.go('myState', {
'stateId': currEvent.stateId
}
);
}
}
);
By my understanding, this should work. But it doesn't. What it does is run the onclick code when I click on any of the circles. At that point it prints out the value of currentEvent.stateId
-- which is always the last one!. So clicking on every circle simply takes me to the same URL - which should only happen when clicking the last circle.
How do I make it so the onclick code uses the value of currentEvent at the time when that circle was drawn, rather than when the click is actually fired? This is a big issue for me.
Upvotes: 2
Views: 2157
Reputation: 32327
The problem is when you are executing the click event the variable currEvent
will have the last value which is your problem.
The correct approach would be to bind the data to the circle.
var myCircle = svg.selectAll(".dots")
.data(eventList).enter().append("circle")//make as many circle as their are events in the eventList. This will bind the data to the circle.
.attr("class", "dots")//set a class to circle for selection to work
.attr("cx", function(d, i) {
return (i * 100)
})
.attr("cy", function(d, i) {
return (i * 100)
})
.attr("r", 5)
.attr("stroke-width", 0)
.attr("fill", "red");
Now register click event to all circles.
myCircle.on({
"click": function(d) {
//here d will give the bound object
console.log("Hello! currEvent.stateId=", d.stateId.toString());
console.log("currEvent = ", d);
}
});
working code here
Upvotes: 2