Add tooltips to your d3 visualizations using Angular Components.
Switch branches/tags
Nothing to show
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
docs-md
docs-styles
docs
e2e
src
.angular-cli.json
.editorconfig
.gitignore
.travis.yml
README.md
demo.gif
karma.conf.js
ng-package.json
package-lock.json
package.json
protractor.conf.js
public_api.ts
tsconfig.json
tslint.json

README.md

ngx-d3-tooltip

Build Status codecov

Add tooltips to your d3 visualizations using Angular Components.

gif of tooltip

Why?

D3.js is a great visualization library, but building dynamic tooltips is a bit clunky. Angular is an app framework and has great html templating and data-binding, which are features that are ideal for more-than-trivial tooltips. This project aims to achieve the best of both worlds.

Installation

  1. Install ngx-d3-tooltip with npm
npm install ngx-d3-tooltip
  1. Add D3TooltipModule to your app module's imports
// ...
import { D3TooltipModule } from 'ngx-d3-tooltip';

// ...in @NgModule:
  imports: [
    D3TooltipModule
  ],
// ...

Usage

The main idea is that the D3TooltipService.createFromComponent method returns a function which is then passed to your d3.Selection.call :

let tooltip = d3TooltipService.createFromComponent(MyComponent, inputs, outputs, options);
svg.selectAll('rect.example')
  .data(myData)
  .enter()
  .call(tooltip);

Here is a more in-depth example:

  1. Create the component you want to use as a tooltip
// my-tooltip.component.ts:

@Component({
  selector: 'my-tooltip',
  template: `
    <h3>{{ myData.name }}</h3>
    <p>{{ myData.someText }}</p>
  `
})
export class MyTooltipComponent {
  
  // Most commonly, you will be passing the d3 element datum
  // to this component, exemplified here (assuming the data
  // bound to the element with this the tooltip is of type 
  // IMyDatum)
  @Input()
  myDatum: IMyDatum;

  // Outputs work as well!
  @Output()
  update: EventEmitter<any>;
}
  1. Add the component to your module's entryComponents array
// app.module.ts:

// ...
import { MyTooltipComponent } from './components/d3-tooltip.component';
import { MyOtherTooltipComponent } from './components/d3-other-tooltip.component';

// ...in @NgModule:
  entryComponents: [
    MyTooltipComponent,
    MyOtherTooltipComponent
  ],
// ...
  1. In your d3 code, create the tooltip function and invoke it with d3.Selection.call
// my-d3-chart.component.ts:
// Import the component tooltip
import { MyTooltipComponent } from './components/d3-tooltip.component';
@Component({ /* ... */ })
export class MyD3ChartComponent {
  tooltip: (selection) => void;  
  constructor(private tipService: D3TooltipService) { // <-- inject the tooltip service
    // create the tooltip function, to be passed to .call()
    this.tooltip = tipService.createFromComponent(
      // The component to insert into the tooltip
      MyTooltipComponent,
      // A function which takes the d3 datum of the current element and returns an object
      // where the keys are @Input property names.
      (d: IMyDatum) => {
        return { myDatum: d }
      },
      // A function which returns an object where keys are @Output property names of the
      // tooltip component and values are handlers passed to the output's subscribe()
      () => {
        return {
          update: (d: IMyDatum) => {
            // do something here...
          }
        }
      },
      { /* other options available */}
    );
  }
  render() {
    // ...set up d3 elements...
    // d3 render code:
    let rect = svg.selectAll('rect.example')
      .data(myData);
    rect.enter()
      .append('rect')
      .classed('example', true)
      .call(this.tooltip); // <-- Use on a selection like this
  }
}

Running the Demo

npm start

Documentation

Documentation

TODOs:

  • tests
  • position: auto support
  • raw template support

License

MIT