[Chartjs]-Bootstrap 3 tabs & Chart.js โ€“ charts not loading on tabs

20๐Ÿ‘

Since the origin of this problem is display none of tab-content in bootstrap Iโ€™ve solved this with a little css hack.

.tab-content>.tab-pane {
    display: block;
    height: 0;
    overflow: hidden;
}
.tab-content>.tab-pane.active {
    height: auto;
}

10๐Ÿ‘

I have had this problem. If I remember correctly I solved it by calling the chart js render when the active tab is shown using shown.bs.tab (http://getbootstrap.com/javascript/#tabs)
i.e.

$('a[data-toggle="tab"]').on('shown.bs.tab', function (e) {
  e.target // newly activated tab
  //call chart to render here
});

Hope that helps.

1๐Ÿ‘

To me the solution is dead simple. Using the latest commit, update the Chart.Arc function as follows:

Chart.Arc = Chart.Element.extend({
    inRange: function (chartX, chartY) {

    var pointRelativePosition = helpers.getAngleFromPoint(this, {
        x: chartX,
        y: chartY
    });

    //Check if within the range of the open/close angle
    var betweenAngles = (pointRelativePosition.angle >= this.startAngle && pointRelativePosition.angle <= this.endAngle),
        withinRadius = (pointRelativePosition.distance >= this.innerRadius && pointRelativePosition.distance <= this.outerRadius);

    return (betweenAngles && withinRadius);
    //Ensure within the outside of the arc centre, but inside arc outer
},
tooltipPosition: function () {
    var centreAngle = this.startAngle + ((this.endAngle - this.startAngle) / 2),
        rangeFromCentre = (this.outerRadius - this.innerRadius) / 2 + this.innerRadius;
    return {
        x: this.x + (Math.cos(centreAngle) * rangeFromCentre),
        y: this.y + (Math.sin(centreAngle) * rangeFromCentre)
    };
},
draw: function (animationPercent) {

    var easingDecimal = animationPercent || 1;

    var ctx = this.ctx;
    var innerRadius = (this.innerRadius < 0) ? this.innerRadius * -1 : this.innerRadius;
    var outerRadius = (this.outerRadius < 0) ? this.outerRadius * -1 : this.outerRadius;

    ctx.beginPath();

    ctx.arc(this.x, this.y, outerRadius, this.startAngle, this.endAngle);

    ctx.arc(this.x, this.y, innerRadius, this.endAngle, this.startAngle, true);

    ctx.closePath();
    ctx.strokeStyle = this.strokeColor;
    ctx.lineWidth = this.strokeWidth;

    ctx.fillStyle = this.fillColor;

    ctx.fill();
    ctx.lineJoin = 'bevel';

    if (this.showStroke) {
        ctx.stroke();
    }
}

});

The thing to take note of is the ternary operator on both inner and outer radius to prevent negative values. This worked like a charm on my project. Charts continued to be responsive and there was NO deleterious effects by converting the radii into natural numbers (ie: positive)

0๐Ÿ‘

Got this fiddle on google search.This might help. http://jsfiddle.net/woqsazau/2/

HTML :

<div class="container">
    <!-- Nav tabs -->
    <ul class="nav nav-tabs" role="tablist" id="bs-tabs">
        <li><a href="#length" role="tab" data-toggle="tab">Length</a>

        </li>
        <li class="active"><a href="#height" role="tab" data-toggle="tab">Height</a>

        </li>
    </ul>
    <!-- Tab panes -->
    <div class="tab-content">
        <div class="tab-pane" id="length">
            <div class="canvas-holder">
                <canvas id="lengthChart" class="chart"></canvas>
            </div>
        </div>
        <div class="tab-pane active" id="height">
            <div class="canvas-holder">
                <canvas id="heightChart" class="chart"></canvas>
            </div>
        </div>
    </div>
</div>

JS :

 function getJSON() {

    var data = {
        "Series": {
            "height": [{
                "Date": "2014-09-19",
                    "Value": 85
            }, {
                "Date": "2014-09-23",
                    "Value": 74
            }]
        }
    };


    console.log(data);
    var series = {};

    // This loop is looping across all the series.
    // x will have all the series names (heights, lengths, etc.).
    for (var x in data.Series) {
        var dates = [];
        var values = [];
        // Loop across all the measurements for every serie.
        for (var i = 0; i < data.Series[x].length; i++) {
            var obj = data.Series[x][i];
            // Assuming that all the different series (heights, lengths, etc.) have the same two Date, Value attributes.
            dates.push(moment(obj.Date).format("MMMM Mo"));
            values.push(obj.Value);
        }
        // Keep the list of dates and values by serie name.
        series[x] = {
            dates: dates,
            values: values
        };
    }

    console.log(series.height.dates);
    console.log(series.height.values);
    //---------
    //valueArray.push(Value);
    //dateArray.push(moment(date).format("MMMM Mo"));

    var dataArray = {
        labels: series.height.dates,
        datasets: [{
            label: "Height",

            strokeColor: "rgb(26, 188, 156)",
            pointColor: "rgba(220,220,220,1)",
            pointStrokeColor: "#fff",
            pointHighlightFill: "#fff",
            pointHighlightStroke: "rgba(220,220,220,1)",
            data: series.height.values
        }]
    };

    function chartFunc(dataArray) {

        var ctx = document.getElementById("heightChart").getContext("2d");
        var myLineChart = new Chart(ctx).Line(dataArray, {
            scaleShowGridLines: true,
            bezierCurve: true,
            bezierCurveTension: 0.4,
            datasetStroke: false,
            fillColor: "rgba(0,0,0,0)",
            datasetFill: false,
            responsive: true,
            showTooltips: true,
            animation: false
        });
    } //chartFunc

    chartFunc(dataArray);
} //getJSON


$(document).ready(function () {

    getJSON();

    $(document).on('shown.bs.tab', 'a[data-toggle="tab"]', function (e) {
        console.log("tab changed");
    });
});

0๐Ÿ‘

I have found a rather easy and somewhat lazy option. You can set all your tabs to โ€œtab-pane activeโ€ This way all your charts on the tabs show and render, then

setTimeout(yourFunction, 250);
function yourFunction()
{
$('.nav-tabs a[href="#anytabExceptdefault"]').tab('show')
$('.nav-tabs a[href="#backtoyourdefaultTab"]').tab('show')

Leave a comment