[Chartjs]-ChartJS charts not generating within tabs

5👍

If you use display:none then chartjs doesn’t know the size to make the chart and then doesn’t. If you switch to jquery.hide()/show() it will work. Here’s a jsfiddle

*The fiddle works without it but if you have a lot of content then you may need to also hide the area temporarily.

Javascript

var data1 = {
    labels: ["January", "February", "March", "April", "May", "June", "July"],
    datasets: [{ data: [65, 59, 80, 81, 56, 55, 40] }]
};
var data2 = {
    labels: ["January", "February", "March", "April", "May", "June", "July"],
    datasets: [{ data: [65, 59, 80, 81, 56, 55, 40] }]
};

// Load each chart and hide() the tab immediately.

var ctx = document.getElementById('chart1').getContext('2d');
var chart1 = new Chart(ctx).Bar(data1);
$('#tab1').hide();

var ctx = document.getElementById('chart2').getContext('2d');
var chart2 = new Chart(ctx).Line(data2);
$('#tab2').hide();

/* 
// will not work because chart is not rendered
$('#tab1_btn').on('click',function(){ 
    $('#tab1').css('display','block'); 
    $('#tab2').css('display','none') })
$('#tab2_btn').on('click',function(){ 
    $('#tab1').css('display','none'); 
    $('#tab2').css('display','block') })
*/

$('#tab1_btn').on('click',function(){ 
    $('#tab1').show(); 
    $('#tab2').hide() 
})
$('#tab2_btn').on('click',function(){ 
    $('#tab1').hide(); 
    $('#tab2').show() 
})

// if you have a lot of content in multiple tabs 
// it may be necessary to temporarily cover the content
$('#tab_cover').hide();

HTML

<button id="tab1_btn">tab1</button>
<button id="tab2_btn">tab2</button>
<div id="tab_cover"> </div>
<div id="tabs">
    <div id="tab1" class="tab">
        <canvas id="chart1" class="chart" width="400" height="300"></canvas>
    </div>
    <div id="tab2" class="tab">
        <canvas id="chart2" class="chart" width="400" height="300"></canvas>
    </div>
</div>

CSS

/* will not work because chart is not rendered
.tab { display:none } */
.chart { width:50% }
.float { float:right; width:50%; }
#tab_cover { background:#9ff; height: 100% !important; width:100%; position: absolute; z-index: 300; }

2👍

I’ve found a solution. I was close with the code I had in the question. It seems that I need to destroy and resize the charts.

I also had to change the display status of the tabs manually.

Here’s what works for me:

    function createNewChart(canvasID) {
        // get the chart data and options from the charts object
        newData = charts[canvasID].data;
        newOptions = charts[canvasID].options;

        // create the new chart
        theChart = document.getElementById(canvasID).getContext("2d"); console.dir(theChart);
        new Chart(theChart).Line(newData, newOptions);
    }

    jQuery('.vertical-nav ul li').click(function(){

        // Target the canvas within the correct tab
        var tabIndex = jQuery(this).index();
        var canvasID = jQuery('.vertical-nav .tab-content:eq( ' + tabIndex + ' ) canvas').attr('id');

        theChart = charts[canvasID].chart;
        builtChart = charts[canvasID].builtChart;

        // Destroy all of the charts so that we can rebuild them
        for (var key in charts) {
            if (charts.hasOwnProperty(key)) {
                jQuery('.vertical-nav .tab-content:eq( ' + tabIndex + ' )').css('display', 'block');
                jQuery('.vertical-nav .tab-content:eq( ' + tabIndex + ' ) .tab-content-chart').css('display', 'block');
                charts[key].builtChart.destroy();
                charts[key].builtChart.resize();
            }
        }

        createNewChart(canvasID);

    }); 

1👍

I was running into the same issues when using hidden divs that only display upon certain selections from a drop-down. What I found to work is similar to what ow3n did. I created the graphs and then had them only generate once the selection was made.

HTML:

<div>
    <select>
        <option value="option-1">Option 1</option>
        <option value="option-2">Option 2</option>
        <option value="option-3">Option 3</option>
    </select>
</div>
<div class="chart1">
    <canvas id="chart1"></canvas>
</div>

<div class="chart2">
    <canvas id="chart2"></canvas>
</div>

<div class="chart3">
    <canvas id="chart3"></canvas>
</div>

Javascript:

//example of chart variables (I only included 1 example)
    var chart1 = {
        labels : ["2009","2010","2011","2012","2013","2014"],
        labelAlign: 'center',
        datasets : [
            {
                label: "Visitor Average",
                fillColor : "rgba(255,255,255,0)",
                strokeColor : "rgba(0,34,221,1)",
                pointColor : "rgba(0,34,221,1)",
                pointStrokeColor : "#fff",
                pointHighlightFill : "#fff",
                pointHighlightStroke : "rgba(0,34,221,1)",
                data: [28, 48, 40, 19, 86, 27]
            },
            {
                label: "Baseline Average",
                fillColor : "rgba(255,255,255,0)",
                strokeColor : "rgba(255,0,0,1)",
                pointColor : "rgba(255,0,0,1)",
                pointStrokeColor : "#fff",
                pointHighlightFill : "#fff",
                pointHighlightStroke : "rgba(255,0,0,1)",
                data: [65, 59, 80, 81, 56, 55]
            }
        ]

    }

window.onload = function(){
    var ctx1 = document.getElementById("chart1").getContext("2d");
    window.myLine1 = new Chart(ctx1).Line(chart1,  {
        responsive: true,
    });
}

//change graph per drop-down selection
    $(document).ready(function(){
        $("select").change(function(){
            $( "select option:selected").each(function(){
                if($(this).attr("value")=="option-1"){
                    $(".chart2").hide();
                    $(".chart3").hide();
                    $(".chart1").show();
                    var ctx1 = document.getElementById("chart1").getContext("2d");
                    window.myLine1 = new Chart(ctx1).Line(chart1,  {
                        responsive: true,
                    });
                }
                if($(this).attr("value")=="option-2"){
                    $(".chart2").show();
                    $(".chart1").hide();
                    $(".chart3").hide();
                    var ctx2 = document.getElementById("chart2").getContext("2d");
                    window.myLine2 = new Chart(ctx2).Line(chart2, {
                        responsive: true,
                    });
                }
                if($(this).attr("value")=="option-3"){
                    $(".chart3").show();
                    $(".chart1").hide();
                    $(".chart2").hide();
                    var ctx3 = document.getElementById("chart3").getContext("2d");
                    window.myLine3 = new Chart(ctx3).Line(chart3, {
                        responsive: true,
                    });
                }
            });
        }).change();
    }); 

0👍

Taking bootstrap’s tab as an example, my solution is to add class .loading-data to .tab-content before rendering using chart.js and remove the class after the rendering is done.

.tab-content.loading-data .tab-pane {
  display: block;
}

In this way, the .tab-panes will display in the instant of chartjs’s rendering.

0👍

Try this one, I struggled with all other approaches but finally done with this code.

$("a").click(function(e){
        let val = '#'+ e.target.href.split("#")[1]
        localStorage.setItem('tab', val)
        window.location.reload();
    })
    $(document).ready(function()
    {
        $('a[href="' + localStorage.getItem('tab') + '"]').parent().addClass('active')
        $(document.getElementById(localStorage.getItem('tab').slice(1))).addClass('active')
    });

Also, try with these approches

window.dispatchEvent(new Event('resize'))
Chartkick.charts["<id of chart element like chart-1>"].redraw()

Leave a comment