Typescript / D3 v4 - The context of this in d3.drag (). on ("end", this.dragended)

I am using the D3 library to move an element in a Venn diagram. When I stop dragging, I want to determine the position of an element in the diagram.

item.call(d3.drag()
    .on("start", this.dragstarted)
    .on("drag", this.dragged)
    .on("end", this.dragended)
);

These are the functions that I call when the drag and drop starts, happens 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 drag is completed. I update some things in the diagram, and then I want to call the save method. This is another method in the class. However, this variable refers to a D3 object, not an instance of a class. This way I get "Uncaught TypeError: cannot read property" save "undefined"

How can I call another method of my class from a drag method?

+4
3

'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))
);
+6

, , d3, :

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));
        }
    }

    ...

}

d3.js v4

+1

D3 this , .. DOM, .

, this "-" , this . :

  • d3.select(this) DOM, DOM, item. , item , , SVGCircleElement, this dragended.
  • this dragended:

, save:

private getDragEndedHandler() {
  let self = this; // object context to preserve
  return function(d: TCMemberScenario, i: number) {
    d3.select(this).classed("active", false); // D3 bound DOM element context
    d.calculateRoles();
    self.save(); // closure-preserved object context
  }
}

, , :

item.call(d3.drag()
    .on("start", this.dragstarted)
    .on("drag", this.dragged)
    .on("end", this.getDragEndedHandler())
);

, .

If you use the latest definitions for d3-selectionand d3-dragfrom npm @types, you will see that they now have common features that will be more explicit with respect to text input thisrelated to DOM elements and D3 callbacks.

0
source

Source: https://habr.com/ru/post/1651219/


All Articles