0

I am taking a d3 project from here https://codepen.io/meerkat00/pen/LQNYrv and converting it to a signle file component VueJS project. Most of it works except for the click handler. Not sure how to go about it.

In the display component method it sets up the click handler for the children/rectangles:

export default {
name: 'TreeMapDrillDown',
components: {d3, Vue},
props: {},
data: function () {
return {
  width: 960,
  height: 600,
  margin: {top: 24, right: 0, bottom: 0, left: 0},
  treemap: null,
  transitioning: false,
  uscg_jsonData : jsonData,
  formatNumber: d3.format(",d"),
  svg: null,
  grandparent: null,
  thisComponent: null
  } 
},
methods: {

 display(d)
 {
   var self = this;
   self.grandparent.datum(d.parent)
   .on("click", transition(d))
   .select("text")
   .text(this.name(d));

   var g1 = self.svg.insert("g", ".grandparent")
     .datum(d)
     .attr("class", "depth");

   var g = g1.selectAll("g").data(d._children).enter().append("g");

   g.filter(function(d){ return d._children})
     .classed("children", true)
     .on("click", transition(d));

  function transition(d)
  {
      var self = this;
      if (self.transitioning || !d) return;
      self.transitioning = true;
  }

 },
 name(d){},
}

The problem is when the object is clicked, and the transition method is called, the scope is for the object clicked - not the vue instance. Using the

self = this; 

technique doesn't work because self is no longer defined at this point. How does one access the vue instance to get to member variables and/or methods?

I tried in the click handler to pass a this into it, but self ends up being undefined, so that didn't work.

display(d)
{
 self = this;

 g.filter(function(d){return d._children})
 .classed("children", true)
 .on("click", transition(d, self));

}
Mike Weber
  • 311
  • 2
  • 16
  • 1
    See the [linked question's answers](http://stackoverflow.com/questions/20279484/how-to-access-the-correct-this-context-inside-a-callback) for how to manage `this`. But if I'm reading the question correctly, you're also **calling** `transition` and passing its return value into `click`, rather than passing the function to click (like [this question with `setTimeout`](https://stackoverflow.com/questions/27643714/settimeout-calls-function-immediately-instead-of-after-delay)). Most likely what you want there is `.on("click", transition.bind(this, d))` (unless `d` will be passed by Vue). – T.J. Crowder Jun 26 '19 at 17:31
  • the `transition.bind(this,d) ` doesn't completely work. No error, but the transition method is not able to access the transitioning member variable of the view instance. 'this' is the object clicked on, and 'd' is the child of that object. So changing that function to `function transition(thing, d) { var self = thing; if (self.transitioning || !d) return; self.transitioning = true; } ` assigns transitioning to self – Mike Weber Jun 26 '19 at 18:01
  • 2
    Classic post question -solve problem scenario. I was able to fix this by moving the transition method out of the display method and into the methods section of the component. I would put it an answer with the formatted code, but I do not see a way to do that. Also, changed the `.on("click", function(d){self.transition(d);})` was required. – Mike Weber Jun 26 '19 at 20:45

0 Answers0