naver / billboard.js

📊 Re-usable, easy interface JavaScript chart library based on D3.js
https://naver.github.io/billboard.js/
MIT License
5.83k stars 351 forks source link

TypeError from arc.ts on mouseover of pie/donut charts #1555

Open bhonermann opened 4 years ago

bhonermann commented 4 years ago

Description

I'm getting a TypeError on mouseover of a donut chart after it's created. Same error occurs when using a pie chart as well:

Uncaught TypeError: Cannot read property 'id' of undefined
    at arc.ts:119
    at Array.forEach (<anonymous>)
    at ChartInternal.updateAngle (arc.ts:134)
    at SVGPathElement.<anonymous> (arc.ts:665)
    at SVGPathElement.<anonymous> (d3.min.js:2)

Working page where the error can be seen is up here

Strangely, the almost exact same code on fiddle here works fine.

I've attempted stripping out all CSS, anything else loading on the page, tried different versions of both billboard and d3, statically assigning the data, but I can't find the source of the error.

Has anyone else experienced this?

netil commented 4 years ago

Hi @bhonermann, when you do mouse interaction the data bound to the <path> element changes for some reason. I think the changes done by your service code, because I did some tests not executing any mouse related code in billboard.js, but still changes the path's data.

You can test this by doing:

// 1) execute first, right after the page loading (not doing any mouse interaction to pie chart)
d3.selectAll(".bb-shapes path").each(function(d) {
    console.log(d);
   // it will print out
   // --> {data: {…}, index: 1, value: 12, startAngle: 3.383253626942854, endAngle: 6.283185307179586, …}
});

// 2) do mouse interaction
// 3) and re-do the '1)' step
d3.selectAll(".bb-shapes path").each(function(d) {
    console.log(d);
    // the correspondent <path> element will print out:
    // {component: "pie_component", indicator: "PS__consenting_participants_arrive_before"}
});

Review your generation code or some possibility where can affect updating <path> element data.

bhonermann commented 4 years ago

Thanks @netil,

Very very interesting. I've managed to identify the issue but it still doesn't make any sense to me. I am dynamically creating divs to hold the chart and the legend.

My original code to create these divs was:

var div = d3.select('div[id="piewrapper'+ind+'"]');

div
    .append('div')
    .attr('id',legenddiv)
    .attr('class','pie_legend');

div
    .append('div')
    .attr('id',chartdiv)
    .attr('class','pie_chart_actual');

Replacing using d3 to create the divs with the pure JS code below fixed it:

var div = document.getElementById('piewrapper'+ind);

var idiv = document.createElement('div');
idiv.setAttribute('id','pie_component_'+ind+'legend');
idiv.setAttribute('class','pie_legend');
div.appendChild(idiv);

var idiv = document.createElement('div');
idiv.setAttribute('id','pie_component_'+ind+'chart');
idiv.setAttribute('class','pie_chart_actual');
div.appendChild(idiv);

All visible attributes of the divs look identical regardless of which set of code is creating them. But the error only occurs when the divs are created utilizing d3 div generation.