0

I am trying to get the combo d3, nvd3 and ng2-nvd3 to work on a Angular 2 project with angular-cli 1.0.0-beta.15.

I have installed the packages with the corresponding @types via npm, package.json looks like this (irrelevant packages omitted):

  "dependencies": {
    "d3": "3.5.16",
    "ng2-nvd3": "1.1.3",
    "nvd3": "1.8.4",
  },
  "devDependencies": {
    "@types/d3": "0.0.33",
    "@types/nvd3": "1.8.32",
    "angular-cli": "1.0.0-beta.15",
  }

I included the d3.js and nv.d3.js as well as nv.d3.css in the angular-cli.json (packages are bundled correctly):

  "styles": [
    "../../../node_modules/nvd3/build/nv.d3.css",
    "styles.scss"
  ],
  "scripts": [
    "../../../node_modules/d3/d3.js",
    "../../../node_modules/nvd3/build/nv.d3.js"
  ],

I created a common module for importing ng2-nvd3 (I verified the code is bundled as well):

import { NgModule } from "@angular/core";
import { nvD3 } from "ng2-nvd3";

@NgModule({
    declarations: [nvD3],
    exports: [nvD3]
})
export class MyCommonModule {
}

Then, I imported the common module into the app module that expects to use it (in the ActivityChartComponent):

@NgModule({
    imports: [PaginationModule, CommonModule, FormsModule, routing, MyCommonModule],
    declarations: [ActivityChartComponent],
    exports: [PlatformComponent]
})
export class PlatformModule {
}

and here is the ActivityChartComponent template (the component code itself just calculates the data, it is irrelevant here):

<h5 class="card-title">{{title}}</h5>
<span *ngIf="description" class="chart-info">{{description}}</span>
<nvd3 [options]="chart" [data]="data"></nvd3>

I am getting an exception ( I masked the URLs in the stack trace with '...' to protect private data):

TypeError: groups.watchTransition is not a function
    at SVGGElement.<anonymous> (http://localhost:8000/.../nv.d3.js:12243:20)
    at http://localhost:8000/.../main.bundle.js:50272:16
    at d3_selection_each (http://localhost:8000/.../main.bundle.js:50278:30)
    at Array.d3_selectionPrototype.each (http://localhost:8000/.../main.bundle.js:50271:12)
    at Array.chart (http://localhost:8000/.../nv.d3.js:11919:19)
    at Array.d3_selectionPrototype.call (http://localhost:8000/.../main.bundle.js:50285:14)
    at SVGGElement.<anonymous> (http://localhost:8000/.../nv.d3.js:6540:25)
    at http://localhost:8000/.../main.bundle.js:50272:16
    at d3_selection_each (http://localhost:8000/.../main.bundle.js:50278:30)
    at Array.d3_selectionPrototype.each (http://localhost:8000/.../main.bundle.js:50271:12)

To be able to debug this - I removed the d3 and nvd3 references from angular-cli.json and I imported them directly into the index.html instead.

Looking at the d3 code, I couldn't find any reference to watchTransition, however nvd3 adds the implementation on d3.selection.prototype.

snippet from nv.d3.js:

d3.selection.prototype.watchTransition = function(renderWatch){
    var args = [this].concat([].slice.call(arguments, 1));
    return renderWatch.transition.apply(renderWatch, args);
};

When debugging, I see the prototype does not have the watchTransition reference...

Any ideas, leads or information would be greatly appreciated.

Sefi Ninio
  • 427
  • 1
  • 5
  • 12

1 Answers1

3

OK, managed to solve this.
The problem was, that when the d3 and nvd3 were bundled via angular-cli.json they were bundled into the scripts.bundle and the application code in main.bundle and that apparently caused them to have different scopes.

I imported them in the common module instead of in the angular-cli config and that made everything be bundled in main.bundle.

So, common module now looks like this:

import { NgModule } from "@angular/core";
import "d3";
import "nvd3";
import { nvD3 } from "ng2-nvd3";

@NgModule({
    declarations: [nvD3],
    exports: [nvD3]
})
export class MyCommonModule {
}
Sefi Ninio
  • 427
  • 1
  • 5
  • 12