Angular 2 and D3 v 4 zoom issue

1,212 views
Skip to first unread message

Jeff Schuenke

unread,
Jan 12, 2017, 6:18:10 PM1/12/17
to d3-js
Hello all,

I am working with Angular 2 D3 v4 and trying to add a zoom feature to a force layout map 
Here is how I add the zoom handler

import * as d3 from 'd3';
import * as d3Force from 'd3-force';
import * as d3Shape from 'd3-shape';
import * as d3Zoom from 'd3-zoom';
import { D3ZoomEvent } from 'd3-zoom';
import * as d3Drag from 'd3-drag';
import {D3DragEvent} from 'd3-drag';
import * as d3Selection from 'd3-selection';

this.svg = this.host.select("svg > g");
this.svg = this.host.append("svg")
                         .attr("width", this.width)
                         .attr("height", this.height)
                         .append("g");
this.defs = this.host.select("svg").append("defs");
this.svg.append("g").attr("class", "links");
this.svg.append("g").attr("class", "nodes");
this.svg.call(d3Zoom.zoom().on("zoom", this.zoomed));

 zoomed() {
        var evt:d3Zoom.D3ZoomEvent<any, any> = d3.event as d3Zoom.D3ZoomEvent<any, any>;
        var tr = evt.transform; 
        this.svg.attr("transform", tr);
        this.svg.selectAll("text").attr("transform", "scale(" + 1/tr.k + ")");
        this.svg.selectAll("path").style("stroke-width", 2/tr.k);
        this.svg.selectAll("circle").style("stroke-width", 2/tr.k);    
    }

Just adding this line causes an error at runtime related to "button"

Here is the error

TypeError: Cannot read property 'button' of null
    at SVGGElement.defaultFilter (http://localhost:8080/js/app.js:29140:29)
    at SVGGElement.mousedowned (http://localhost:8080/js/app.js:29363:33)
    at SVGGElement.<anonymous> (http://localhost:8080/js/app.js:13069:17)
    at ZoneDelegate.invokeTask (http://localhost:8080/js/polyfills.js:14624:36)
    at Object.onInvokeTask (http://localhost:8080/js/vendor.js:24682:42)
    at ZoneDelegate.invokeTask (http://localhost:8080/js/polyfills.js:14623:41)
    at SVGGElement.ZoneTask.invoke (http://localhost:8080/js/polyfills.js:14694:34)
  -------------   Elapsed: 13088 ms; At: Thu Jan 12 2017 15:09:33 GMT-0800 (PST)   -------------  
    at Object.onScheduleTask (http://localhost:8080/js/polyfills.js:15875:19)
    at ZoneDelegate.scheduleTask (http://localhost:8080/js/polyfills.js:14601:50)
    at Zone.scheduleEventTask (http://localhost:8080/js/polyfills.js:14533:40)
    at zoneAwareAddListener (http://localhost:8080/js/polyfills.js:15183:15)
    at SVGGElement.addEventListener (eval at createNamedFn (http://localhost:8080/js/polyfills.js:15286:18), <anonymous>:3:43)
    at SVGGElement.<anonymous> (http://localhost:8080/js/app.js:13112:11)
    at Selection.selection_each [as each] (http://localhost:8080/js/app.js:13481:38)
    at Selection.selection_on [as on] (http://localhost:8080/js/app.js:13136:33)


I am unable to resolve this.  Any help, please?

Jeff Schuenke

unread,
Jan 12, 2017, 6:20:24 PM1/12/17
to d3-js
One more thing,  this same code works correctly in plain JS in a browser.  THis is a TypeScript or Angular 2 issue only.  The error occurs when clicking on the main SVG element where no other items are.

Vlado Z

unread,
Jan 13, 2017, 9:33:47 AM1/13/17
to d3-js
Just to mention, I think "this" inside zoomed() is not the same "this" outside of zoomed(), so perhaps when you click on a button it cannot find it inside the SVGElement or whatever is that where you click.

Vlado Z

unread,
Jan 13, 2017, 9:36:46 AM1/13/17
to d3-js
if you type

this.svg = something;

then

zoomed () {
    this.svg.doSomething(); // would not work because this inside "this" of the function references the function scope which does not contain property svg.
}
Reply all
Reply to author
Forward
0 new messages