I am using the D3 library to move an item within a Venn-diagram. When I stop dragging I want to determine the position of the item in the diagram.
item.call(d3.drag()
.on("start", this.dragstarted)
.on("drag", this.dragged)
.on("end", this.dragended)
);
These are the functions I call when the dragging starts, is going on and ends.
dragended(d: TCMemberScenario, i: number) {
d3.select(this).classed("active", false);
d.calculateRoles();
this.save();
}
This is the function that is called when the dragging has ended. I update some things in the diagram and then I want to call the save method. This is another method in the class. However, the this variable is referencing to the D3 object and not the instance of the class. So I get a "Uncaught TypeError: Cannot read property 'save' of undefined"
How can I call from the dragended method another method of my class?
To keep reference to 'this' use arrow functions like this:
item.call(d3.drag()
.on("start", (d, i) => this.dragstarted(d,i))
.on("drag", (d, i) => this.dragged(d, i))
.on("end", (d, i) => this.dragended(d, i))
);
If you need to keep the reference to the class instance and also the element instance referenced by d3 drag you can define your listener functions as:
export class MyClass {
@Input()
radius: number = 45;
constructor() {
d3.drag()
.on("start", this.dragStarted(this))
.on("drag", this.dragged(this))
.on("end", this.dragEnded(this));
}
private dragged(self) {
return function(d) {
// 'this' in this context will be the d3 element
d3.select(this)
.attr("cx", d.x = self.radius * Math.cos(alpha))
.attr("cy", d.y = d3.event.y < 0 ? -self.radius * Math.sin(alpha) : self.radius * Math.sin(alpha));
}
}
...
}
Tested with d3.js v4
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