Martin B.
Martin B.

Reputation: 72

d3.drag() in Angular2

Still can't find out how to use d3.drag() in Angular2 component.

Trying:

d3.selectAll(".node").call(d3.drag().on("start", started));

But getting "Unresolved function or method drag()".

I have installed d3, it is working quite well. I have imported d3 using import * as d3 from 'd3'. Here is an example of my code:

import {Component, OnInit} from '@angular/core';
import * as d3 from 'd3';
// some other imports

@Component({
    selector: 'model-detail-d3',
    inputs: ['modelData'],
    templateUrl: 'app/shared/templates/d3.html',
    //styleUrls:  ['app/replication-model/d3.css']
    providers: [DataModel]
})
export class ModelDetailD3Component implements OnInit {

    private modelData : ModelData;

    constructor(private someModel: SomeModel) {
        this.someModel= someModel;
    }

    ngOnInit() {

        this.someModel.setInstanceData(this.modelData);

        var someItems: someItems[];
        someItems = [];
        if (this.someModel.getInstances()) someInstances = this.someModel.getInstances();

        // d3 container
        var svgContainer = d3.select("#d3-model")
            .append("svg")
            .attr("width", 600)
            .attr("height", 300);

        var d3Items = svgContainer.selectAll("rect")
            .data(someInstances)
            .enter()
            .append("rect");


        var defaultX = 10;
        var defaultY = 10;
        var spiAttributes = spiItems
            .attr("x", function (spiItem, i) { return 10 + (someItem.d3.x || 10*i*defaultX); })
            .attr("y", function (spiItem, i) { return 10 + (someItem.d3.y || 10*i*defaultY); })
            .attr("height", function (someItem) { return (50); })
            .attr("width", function (someItem) { return (80); })
            .style("fill", function(someItem) { return "red"; })
            // Add event to each item
            .on('mouseover', (someItem) => {
                this.onMouseOn(someItem);
            })
            .on('mouseout', (someItem) => {
                this.onMouseOut();
            })
            .append('rect');

        // HERE IS THE PROBLEM: "Unresolved function or method drag()"
        svgContainer
            .call(d3.drag()
                .container(svgContainer)
                .on("start", dragstarted)
                .on("drag", dragged)
                .on("end", dragended));

        // d3.selectAll("rect").call(d3.drag().on("start", started));
    };

So I can use D3 in Angular2 to draw some items according to some data, but I am not able to make some behavior as drag or zoom, even if it is working in some js examples as here http://bl.ocks.org/enjalot/1378144 or https://bl.ocks.org/mbostock/6123708 , but not in Angular2.

Upvotes: 1

Views: 2895

Answers (4)

Naveen Reddy
Naveen Reddy

Reputation: 19

Because D3 is not implemented in typescript. Which follows strict typings.we need to typecast d3.drag() to (< any>d3).drag()

Hope it works.

Upvotes: 0

tomwanzek
tomwanzek

Reputation: 1096

For an example of how to use d3-drag in a component, have a look at the following drag-zoom-2 Angular component example. While the example uses d3-ng2-service it should give you a basic idea:

  • use a service to get access to d3, this could possibly your own customization
  • create the callbacks you need for d3-drag event handling,
  • attach the event handlers in the appropriate Angular lifecycle hooks.

As an important consideration, be aware that, by design, the this scope of a d3-drag callback is the selected element, not the this scope of your Angular component! So, if you require access to members of the Angular component in the callback, use a drag event handler returned from a closure providing you access to the Angular component.

This could mean adding a private Angular component method, like:

private getDragHandler() {
  const self = this;
  return function dragged(this: SVGCircleElement, d: PhyllotaxisPoint) {
    let e: D3DragEvent<SVGCircleElement, PhyllotaxisPoint, PhyllotaxisPoint> = d3.event;

    // Use self.foo to access the foo member of the Angular component.

    d3.select(this).attr('cx', d.x = e.x).attr('cy', d.y = e.y);
  }
}

Note that the code snippet here is an alternative to the implementation details in "drag-zoom-2".

Upvotes: 2

Martin B.
Martin B.

Reputation: 72

So I haven't found out how to use the function drag() of D3 in Angular2 with version 4 of D3, but it works well with version 3 of D3.

Upvotes: -2

Poul Kruijt
Poul Kruijt

Reputation: 71911

In order to use d3.drag() you have to install the d3-drag package:

npm install d3-drag

Upvotes: 2

Related Questions