coderdark
coderdark

Reputation: 1501

D3, TS and Angular 2

I am trying to use D3 v4 with Angular 2 (Typescript). I am currently looking into D3 v4. I was able to follow some of the answers here in stackoverflow with similar issues with no success. I have imported most of the D3 libraries and its typings ( I am using TS 2.0) and in my component file I require import * as d3 from 'd3';. This issue to me might be Angular 2, Typescript and 3rd party libraries... so far a mess.

In my component file I have some code like this:

        let arc = d3.arc()
            .outerRadius(chartHeight / 2)
            .innerRadius(chartHeight / 4)
            .padAngle(0.03)
            .cornerRadius(8);

        let pieG = chartLayer.selectAll("g")
            .data([data])
            .enter()
            .append("g")
            .attr("transform", "translate(" + [chartWidth / 2, chartHeight / 2] + ")");

        let block = pieG.selectAll(".arc")
            .data(arcs);

        let newBlock = block.enter().append("g").classed("arc", true);

        newBlock.append("path")
            .attr("d", arc)
            .attr("id", function (d, i) {
                return "arc-" + i
            })
            .attr("stroke", "gray")
            .attr("fill", function (d, i) {
                return d3.interpolateCool(Math.random())
            });

As you can see I have defined arc on the first line and using it in line 19 but I get an error:

[at-loader] src\piechart\piechart.component.ts:19:28
    Argument of type 'Arc<any, DefaultArcObject>' is not assignable to      parameter of type '(this: BaseType, datum: PieArcDatum<number | { valueOf():    number; }>, index: num
  ber, groups: Base...'.
  Types of parameters 'd' and 'datum' are incompatible.
    Type 'PieArcDatum<number | { valueOf(): number; }>' is not assignable to type 'DefaultArcObject'.
      Property 'innerRadius' is missing in type 'PieArcDatum<number | { valueOf(): number; }>'.

The Arch and arc seem to be defined in the d3-shape types and also in the d3-path types.

Anyone that can help me... I have spent days trying to do a POC with angular 2, TS and D3 v4 and so far no luck... I have seen all the articles online about it and most of them have older version or not working. It seems too me that this is a typing issue. Angular 2 and third party libraries are a nightmare.

Upvotes: 8

Views: 7272

Answers (5)

Tim Perkins
Tim Perkins

Reputation: 2389

You just need to add a type when you create the arc. Try something like this:

interface Datum {
  key: string;
  value: number;
}

const pieData = d3.pie<Datum>()
  .value(d => d.value)(data);

const arc = d3.arc<d3.PieArcDatum<Datum>>();

d3.select('#pie')
  .data(pieData)
  .enter()
  .append('path')
  .attr('d', arc);

Upvotes: 7

jovani
jovani

Reputation: 849

Just need to cast arc as any. So it should be .attr("d", <any>arc)

Upvotes: 17

Bruce MacDonald
Bruce MacDonald

Reputation: 288

I added the import statement in my Angular 2 project and kept getting errors in development. I'm using angular-cli and d3 v4.

In addition to import * as d3 from "d3"; add the code below to your typings.d.ts file:

declare module 'd3' {
  export * from 'd3-array';
  export * from 'd3-axis';
  export * from 'd3-brush';
  export * from 'd3-chord';
  export * from 'd3-collection';
  export * from 'd3-color';
  export * from 'd3-dispatch';
  export * from 'd3-drag';
  export * from 'd3-dsv';
  export * from 'd3-ease';
  export * from 'd3-force';
  export * from 'd3-format';
  export * from 'd3-geo';
  export * from 'd3-hierarchy';
  export * from 'd3-interpolate';
  export * from 'd3-path';
  export * from 'd3-polygon';
  export * from 'd3-quadtree';
  export * from 'd3-queue';
  export * from 'd3-random';
  export * from 'd3-request';
  export * from 'd3-scale';
  export * from 'd3-selection';
  export * from 'd3-shape';
  export * from 'd3-time';
  export * from 'd3-time-format';
  export * from 'd3-timer';
  export * from 'd3-transition';
  export * from 'd3-voronoi';
  export * from 'd3-zoom';
}

Any errors I was getting (and seeing them only in development) went away when I included this code. Hope this helps you rule out typings errors and gets you closer to a solution!

Upvotes: 2

Wolfgang Kuehn
Wolfgang Kuehn

Reputation: 12936

The following code draws one arc. You may supply more items to arcData:

import * as d3 from "d3";

export function run() {
  const chartLayer = d3.select('svg');

  let chartHeight = 500;
  let chartWidth = 500;
  let data = null;

  let arcData = [{
          innerRadius: 0,
          outerRadius: 100,
          startAngle: 0,
          endAngle: Math.PI / 2,
          padAngle: 1
       }];

  let arc = d3.arc();

  let pieG = chartLayer 
      .selectAll("g").data([data]).enter()
      .append("g")
      .attr("transform", "translate(" + [chartWidth / 2, chartHeight / 2] + ")");

  let block = pieG.selectAll(".arc")
      .data(arcData);

  let newBlock = block.enter().append("g").classed("arc", true);

  newBlock.append("path")
      .attr("d", function (d) { return arc(d) })
      .attr("id", function (d, i) {
          return "arc-" + i
      })
      .attr("stroke", "gray")
      .attr("fill", function (d, i) {
          return d3.interpolateCool(Math.random())
      });
}

Btw, my guess is that you do not need the line

.selectAll("g").data([data]).enter()

Upvotes: 0

Tudor Ciotlos
Tudor Ciotlos

Reputation: 1845

Try this when appending the path:

newBlock.append("path")
    .attr("d", arc())
    .attr("id", function (d, i) {
        return "arc-" + i
    })
    .attr("stroke", "gray")
    .attr("fill", function (d, i) {
        return d3.interpolateCool(Math.random())
    });

According to the d3 API, after constructing an arc generator using let arc = d3.arc(), you have to call arc() in order to generate the actual arc.

Upvotes: 0

Related Questions