2

Trying to implement a D3 chart (sankey) to the latest version of Angular. I followed this gist, but the only thing I get is the Nodes in plain text instead of the graph.

I made a plunker with a minimum installation to reproduce the issue

Short story,

I import the libraries on my component:

import * as d3 from 'd3';
import * as d3Sankey from 'd3-sankey';

Called a DrawChart() on ngOnInit:

ngOnInit() {
      this.DrawChart();
}

Implement the DrawChart() function:

private DrawChart() {

            var svg = d3.select("#sankey"),
                width = +svg.attr("width"),
                height = +svg.attr("height");

            var formatNumber = d3.format(",.0f"),
                format = function (d: any) { return formatNumber(d) + " TWh"; },
                color = d3.scaleOrdinal(d3.schemeCategory10);

            var sankey = d3Sankey.sankey()
                .nodeWidth(15)
                .nodePadding(10)
                .extent([[1, 1], [width - 1, height - 6]]);

            var link = svg.append("g")
                .attr("class", "links")
                .attr("fill", "none")
                .attr("stroke", "#000")
                .attr("stroke-opacity", 0.2)
                .selectAll("path");

            var node = svg.append("g")
                .attr("class", "nodes")
                .attr("font-family", "sans-serif")
                .attr("font-size", 10)
                .selectAll("g");

            d3.json("../../../assets/vendors/uk2015.json", function (error, energy: any) {
                if (error) throw error;

                sankey(energy);

                link = link
                    .data(energy.links)
                    .enter().append("path")
                    .attr("d", d3Sankey.sankeyLinkHorizontal())
                    .attr("stroke-width", function (d: any) { return Math.max(1, d.width); });

                link.append("title")
                    .text(function (d: any) { return d.source.name + " → " + d.target.name + "\n" + format(d.value); });

                node = node
                    .data(energy.nodes)
                    .enter().append("g");

                node.append("rect")
                    .attr("x", function (d: any) { return d.x0; })
                    .attr("y", function (d: any) { return d.y0; })
                    .attr("height", function (d: any) { return d.y1 - d.y0; })
                    .attr("width", function (d: any) { return d.x1 - d.x0; })
                    .attr("fill", function (d: any) { return color(d.name.replace(/ .*/, "")); })
                    .attr("stroke", "#000");

                node.append("text")
                    .attr("x", function (d: any) { return d.x0 - 6; })
                    .attr("y", function (d: any) { return (d.y1 + d.y0) / 2; })
                    .attr("dy", "0.35em")
                    .attr("text-anchor", "end")
                    .text(function (d: any) { return d.name; })
                    .filter(function (d: any) { return d.x0 < width / 2; })
                    .attr("x", function (d: any) { return d.x1 + 6; })
                    .attr("text-anchor", "start");

                node.append("title")
                    .text(function (d: any) { return d.name + "\n" + format(d.value); });
            });
        }

    }

No error on console or something that will point me to the right direction.

Edit: I tried to copy paste the SVG code from the code inspector in Chrome and render it in an online SVG viewer and it works. It seems that Angular cannot render the SVG that it produces. But how I can fix it?

Tasos
  • 7,325
  • 18
  • 83
  • 176
  • Hi, I am struggling with the same issue, namely how to embed a D3 graph into Angular 6. I got a working (local) version of the D3-graph as HTML-file and TSV-input, but what is the correct way to implement it into Angular? Did you solve your issue? – B--rian Aug 23 '18 at 06:58
  • @B--rian unfortunately I didn't solve it – Tasos Aug 24 '18 at 12:00

1 Answers1

1

The code did not work for me as well. It didn't render, because it wasn't set as a svg-element.

Replace

var svg = d3.select("#sankey")

with

var svg = d3.select('#sankey')
    .append('svg')
    .attr('width', 1000)
    .attr('height', 500);

Your DOM will now show the svg element and it should work.