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.
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();
}
});
{...}
}