3

I have a basic diagram in D3.js, containing objects and relations between objects initialized in these arrays:

let objectsData = [
  { id: 1, x: 150, y: 150, type: "circle", color: "#ff6b6b" },
  { id: 2, x: 300, y: 200, type: "rect", color: "#4ecdc4" },
  { id: 3, x: 500, y: 150, type: "circle", color: "#45b7d1" },
  { id: 4, x: 400, y: 350, type: "rect", color: "#96ceb4" },
  { id: 5, x: 200, y: 400, type: "circle", color: "#feca57" },
];

let relationsData = [
  { source: 1, target: 2 },
  { source: 2, target: 3 },
  { source: 3, target: 4 },
  { source: 4, target: 5 },
];

When my updateRelations() method is first called, everything is displayed correctly, but as I click relations to remove them, they are always removed from last to first in the relationsData table, it's never the one that's been clicked that is removed:

const relations = svg.append("g").attr("class", "relations");

function updateRelations() {
  const relationGroups = relations.selectAll(".relation-group").data(relationsData);

  const enterGroups = relationGroups
  .enter()
  .append("g")
  .attr("class", "relation-group")
  .style("cursor", "pointer")
  .on("click", function (event, d) {
    event.stopPropagation();
    const index = relationsData.indexOf(d);
    if (index > -1) {
      relationsData.splice(index, 1);
      updateRelations();
    }
  });

  // Add visible line
  enterGroups
    .append("line")
    .attr("class", "relation");

  const allGroups = enterGroups.merge(relationGroups);

  allGroups.selectAll(".relation")
  .attr("x1", (d) => getObjectById(d.source).x)
  .attr("y1", (d) => getObjectById(d.source).y)
  .attr("x2", (d) => getObjectById(d.target).x)
  .attr("y2", (d) => getObjectById(d.target).y);

  relationGroups.exit().remove();
}

function getObjectById(id) {
  return objectsData.find((obj) => obj.id === id);
}

At first I thought it was my index variable that was miscalculated (like : it would always be -1), but its value seems correct.

1 Answer 1

2

You could use findIndex to match by property.

// Add unique id
let relationsData = [
  { id: 'rel1', source: 1, target: 2 },
  { id: 'rel2', source: 2, target: 3 },
  { id: 'rel3', source: 3, target: 4 },
  { id: 'rel4', source: 4, target: 5 },
];

function updateRelations() {
  // Use key function with id 
  const relationGroups = relations.selectAll(".relation-group").data(relationsData, d => d.id);
  // ...

  const enterGroups = relationGroups
    .enter()
    .append("g")
    .attr("class", "relation-group")
    .style("cursor", "pointer")
    .on("click", function (event, d) {
      event.stopPropagation();
      
      // Use findIndex to match
      const index = relationsData.findIndex(rel => rel.id === d.id);
      if (index > -1) {
        relationsData.splice(index, 1);
        updateRelations();
      }
    });
  // ...
}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.