0.2.0 • Published 6 years ago

ngx-d3-tooltip v0.2.0

Weekly downloads
9
License
MIT
Repository
github
Last release
6 years ago

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
  2. 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>;
    }
  2. 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
      ],
    // ...
  3. 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