I'm creating horizontal tree from nested array. After tree is created, the links from one node to another are regularly being updated, but the removal functionality is not working.
import { Component, OnInit } from '@angular/core';
import * as d3 from 'd3';
@Component({
selector: 'app-rtm-graph',
templateUrl: './rtm-graph.component.html',
styleUrls: ['./rtm-graph.component.css']
})
export class RtmGraphComponent implements OnInit {
private rtmData: {id:number, name: string, children: any[] } =
{ id: 0, name: 'RTM', children: [
{ id: 0, name: 'RTM', children: [
{ id: 0, name: 'RTM', children: []},
{ id: 0, name: 'RTM', children: []},
{ id: 0, name: 'RTM', children: []},
]},
{ id: 0, name: 'RTM', children: []},
] };
private svg: any;
private margin = 50;
private width = 750 - (this.margin * 2);
private height = 750 - (this.margin * 2);
private root: any;
private treemap = d3.tree().size([this.height, this.width])
private duration = 1124;
private i = 0;
constructor(public _rs:RootService) { }
ngOnInit(): void {
this.createSvg();
this.createTree()
}
private callSvg() {
return d3.select("figure#rtm-graph");
}
private createTree(): void {
this.root = d3.hierarchy(this.rtmData, (d) => {
return d.children;
})
this.root.x0 = this.height / 2;
this.root.y0 = 0;
this.update(this.root);
}
private createSvg(): void {
this.svg = this.callSvg()
.append("svg")
.attr("width", this.width + (this.margin * 2))
.attr("height", this.height + (this.margin * 2))
.append("g")
.attr("transform", `translate(${this.margin},${this.margin})`);
}
private update(source): void {
let treedata = this.treemap(this.root);
let nodes = treedata.descendants();
nodes.forEach(d => {
d.y = d.depth * this.width / 5;
});
let node = this.svg.selectAll("g.node").data(nodes, (d) => d.id || (d.id = ++this.i));
// links
let links = treedata.descendants().slice(1);
let link = this.svg.selectAll('path.link').data(links, (d) => {
return d.id;
})
let linkEnter = link
.enter()
.insert('path', 'g')
.attr('class', 'links')
.attr('d', (d) => {
let o = { x: source.x0, y: source.y0 + 40 }
return this.diagonal(o, o)
})
let linkUpdate = linkEnter.merge(link);
linkUpdate
.transition()
.duration(this.duration)
.attr("d", (d) => {
return this.diagonal(d, d.parent);
});
link
.exit()
.transition()
.attr('d', (d: any) => {
console.log("Inside link exit")
let o = { x: source.x0, y: source.y0 }
return this.diagonal(o, o);
})
.remove();
let nodeEnter = node
.enter()
.append("g")
.attr("class", "node")
.attr("transform", d => {
return `translate(${source.y0 + 20},${source.x0})`
})
.on("click", this.clicked.bind(this))
nodeEnter.append('circle')
.attr('class', 'node')
.attr('r', 0)
.style('fill', d => {
return d._children ? "red" : "white";
})
let nodeUpdate = nodeEnter.merge(node);
nodeUpdate.transition()
.duration(this.duration)
.attr("transform", d => `translate(${d.y + 20},${d.x})`)
.attr("opacity", 1)
nodeUpdate.select("circle.node")
.attr('r', 10)
.style("fill", d => d._children ? "red" : "black")
.attr("cursor", "pointer");
nodeUpdate.append('rect')
.attr('x', 0)
.attr('y', -20)
.attr('rx', 5)
.attr('ry', 5)
.attr('width', 80)
.attr('height', 40)
.attr('fill', 'grey')
.exit();
nodeUpdate.append('text')
.attr('x', 0)
.attr('y', 0)
.attr('dx', 10)
.text(d => {
console.log(d.data.name)
return d.data.name;
});
let nodeExit = node.exit()
.transition()
.duration(this.duration)
.attr("transform", function () { return `translate(${source.y + 20},${source.x})` })
.attr("opacity", 0.5)
.remove();
// collapsing of the nodes
nodes.forEach(d => {
d.x0 = d.x;
d.y0 = d.y;
})
}
diagonal(s, d) {
let path = `M ${s.y} ${s.x}
C ${(s.y + d.y) / 2} ${s.x}
${(s.y + d.y) / 2} ${d.x}
${d.y} ${d.x}`;
return path;
}
clicked(event, d) {
console.log('ddddd:::',d);
if (d.children) {
d._children = d.children;
d.children = null;
} else {
d.children = d._children;
d._children = null;
}
this.update(d);
}
}
If I add console.log("Inside link exit")
to the code, then no log is written to the console. But if I run same code in vanilla JavaScript, then I get the expected output from this console.log
.
For the first time, the graph is generated correctly.
but after collapsing nodes, the output is as follows:
How to remove this residual link?