Stetzon
Stetzon

Reputation: 739

Adding new data to empty Chart.js chart does not render new data correctly

I have a Chart.js bar chart that gets instantiated on page load. I then wish to add data to the chart as it becomes available (no data is available at the time of its creation). However, passing in new data always seems to have the chart fail to render the first set of data passed in:

var bar_chart_data = {
labels: [],
datasets: [
    {
        label: "My First dataset",
        fillColor: "rgba(220,220,220,0.5)",
        strokeColor: "rgba(220,220,220,0.8)",
        highlightFill: "rgba(220,220,220,0.75)",
        highlightStroke: "rgba(220,220,220,1)",
        data: []
    }
]
};

var ctx = $("#bar-chart").get(0).getContext("2d");
var bar_chart = new Chart(ctx).Bar(bar_chart_data);

bar_chart.addData([2], "test")
bar_chart.addData([2], "test2")

I have tried a variety of things, including:

jsfiddle

Upvotes: 0

Views: 5108

Answers (1)

Quince
Quince

Reputation: 15000

The issue was inside the scale class when the chart was trying to calculateX with no data in the graph. It would result in infinity when no data was in there and this was messing up the graph. so you can override Chart.Scale.calculateX like this: ( http://jsfiddle.net/leighking2/3nrhtyz4/ ) Edit - @Matt Humphrey pointed out the fix did not work for Line graphs so here is an update based on his github comment (github.com/nnnick/Chart.js/issues/573#issuecomment-56102121)

   Chart.Scale = Chart.Scale.extend({
    calculateX: function (index) {
        //check to ensure data is in chart otherwise we will get inifinity
        if (!(this.valuesCount - (this.offsetGridLines ? 0 : 1))) {
            return 0;
        }
        var isRotated = (this.xLabelRotation > 0),
            // innerWidth = (this.offsetGridLines) ? this.width - offsetLeft - this.padding : this.width - (offsetLeft + halfLabelWidth * 2) - this.padding,
            innerWidth = this.width - (this.xScalePaddingLeft + this.xScalePaddingRight),
            valueWidth = this.valuesCount === 0 ? 0 : innerWidth / (this.valuesCount - ((this.offsetGridLines) ? 0 : 1)),
            valueOffset = (valueWidth * index) + this.xScalePaddingLeft;

        if (this.offsetGridLines) {
            valueOffset += (valueWidth / 2);
        }

        return Math.round(valueOffset);
    },
});

You can now just use chart js normally as before.

var bar_chart_data = {
    labels: [],
    datasets: [{
        label: "My First dataset",
        fillColor: "rgba(220,220,220,0.5)",
        strokeColor: "rgba(220,220,220,0.8)",
        highlightFill: "rgba(220,220,220,0.75)",
        highlightStroke: "rgba(220,220,220,1)",
        data: []
    }, {
        label: "My Second dataset",
        fillColor: "rgba(151,187,205,0.5)",
        strokeColor: "rgba(151,187,205,0.8)",
        highlightFill: "rgba(151,187,205,0.75)",
        highlightStroke: "rgba(151,187,205,1)",
        data: []
    }]
};

var bar_chart_options = {
    responsive: false
};

var ctx = $("#bar-chart").get(0).getContext("2d");
var bar_chart = new Chart(ctx).Bar(bar_chart_data, bar_chart_options);

bar_chart.addData([1, 1], "test")
bar_chart.addData([2, 2], "test2")

Upvotes: 1

Related Questions