Add tooltips to your d3 visualizations using Angular Components.
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.
- Install
ngx-d3-tooltip
withnpm
npm install ngx-d3-tooltip
- Add
D3TooltipModule
to your app module'simports
// ...
import { D3TooltipModule } from 'ngx-d3-tooltip';
// ...in @NgModule:
imports: [
D3TooltipModule
],
// ...
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:
- 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>;
}
- 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
],
// ...
- 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
}
}
npm start
- tests
- position: auto support
- raw template support
MIT