Integrate an interactive chart in a tooltip with bootstrap 4,tippy.js and chart.js

I was asked to show a pie chart in an bootstrap based application I am developing. And I had to find a solution to archive this. Unfortunally I haven’t found an out of the box solution by searching for it.

Tools and Libraries I’ve choosen to archive this goal:

To create an interactive chart I’ve choosen the opensource library https://www.chartjs.org/ .

As using the integrated tooltips in bootstrap 4 haven’t had the opportunity to bind an existing html element, I’ll use https://atomiks.github.io/tippyjs/ as this is also suggested by the authors of popper.js. And popper.js is used for the build in tooltips of bootstrap anyway.

Let’s start with some html…

The html template for the popup. This contains an canvas which we will use to draw the chart later.

<div id="template" style="display: none;"><canvas width="150" height="150" data-rendered="false"></canvas><button type="button" class="btn btn-link">Click here to see the details</button></div>

Creating the span with the tooltip. This is not too special I think :)

<span id="tooltip">Hover over me to see a cool chart</span>

Creating a details container to show the chart on the screen later. After a user interaction and to have it sticky.

<div id="details" class="d-none col"><h1>Chart details</h1><canvas width="400" height="400" data-rendered="false"></canvas></div>

And now the JavaScript part…

Rendering a currently displayed canvas to a pie chart is done by this function. I’m using JQuery to find the currently displayed canvas with `$(‘canvas[data-rendered=”false”]:visible’)`. The rest is just the example from chart.js

function renderChart() {var canvas = $('canvas[data-rendered="false"]:visible');canvas.data('rendered', 'true');var ctx = canvas.get();var myPieChart = new Chart(ctx, {  type: 'pie',  data: {  datasets: [{  data: [10, 20, 30]  }],  labels: [    'Red',    'Yellow',    'Blue'    ]  }});}

Showing the details area

function showDetails() {  $('#details').removeClass('d-none');  setTimeout(renderChart, 500);}

And now the final javascript to make the tooltip work. First of all I’m selecting my template. Then I’m telling tippy to genereate a tool tip for the span above `tippy(‘#tooltip’,`. The content is set to my template and I’m making the tooltip “interactive” and also “allowHTML”. This is not really interesting.

The interesting part is the onShown method. I’m using this to render the chart via my renderChart function. And this is as you know grabbing the current visible canvas to render the chart in it.

After rendering I’m binding a click on my “details” button from the template. And this is just showing the details div, which includes rendering there as well.

const template = document.getElementById('template');tippy('#tooltip', {  content: template.innerHTML,  allowHTML: true,  interactive: true,  onShown(instance) {     renderChart();     const $button = $('button');     $button.click(() => {     instance.hide();     showDetails();    });  },});

That’s all.

See my gist on github for the full code:

https://gist.github.com/Bjego/24b30a7c690642eaac150822e49c5335