'Transforming D3 code into Vue3 - cells not being added to rows but into HTML

I found a GitHub version of Mike Bostock's adjacency matrix visualization, using data from Les Miserables.

I transformed it into Vue3 code, but since this is my first project, I probably made some mistakes. The cells that should be added to each row, are added to the main HTML and the visualization is not appearing (black screen).

Here is an online version of the transformed visualization in Vue3 format: https://codesandbox.io/s/sweet-gould-dejiuj?file=/src/components/Miserables.vue:33765-33857

black output



Solution 1:[1]

This is because the context of the method roww() is not the proper context.

A row is created with the following code :

const row = this.svg
  .selectAll(".row")
  .data(this.matrix)
  .enter()
  .append("g")
  .attr("class", "row")
  .attr("transform", (d, i) => `translate(0,${this.x(i)})`)
  .each(this.roww); 

The last line call this.roww for each node of the selection, but the context of that function (this keyword inside this.roww) is somehow hardcoded to the object it is a member of, so it does not receive the proper context which should be the actual node object which relates to the DOM.

To fix that, you need to use a regular function created using function keyword (not an arrow functon for the same reason as above) so that it can be passed the correct context, though since your function precisely relies on its "parent" context (the other this), you will have to set a variable referring to it in the outer scope so it can be read within the function :

// ...

const that = this;

function fillrow (row) {
  // eslint-disable-next-line no-unused-vars
  const cell = d3.select(this).selectAll(".cell")
    .data(row.filter((d) => d.z))
    .enter()
    .append("rect")
    .attr("class", "cell")
    .attr("x", (d) => that.x(d.x))
    .attr("width", that.x.bandwidth())
    .attr("height", that.x.bandwidth())
    .style("fill-opacity", (d) => that.z(d.z))
    .style("fill", (d) =>
      that.get_nodes[d.x].group === that.get_nodes[d.y].group
        ? that.c(that.get_nodes[d.x].group)
        : null
    )
    .on("mouseover", that.mouseover)
    .on("mouseout", that.mouseout);
}

const row = this.svg
  .selectAll(".row")
  .data(this.matrix)
  .enter()
  .append("g")
  .attr("class", "row")
  .attr("transform", (d, i) => `translate(0,${this.x(i)})`)
  .each(fillrow);

// ...

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 EricLavault