Kenneth D. Kenneth D. - 3 months ago 52
Javascript Question

c3.js how to update x-axis labels on chart.load()?

I have a c3.js timeseries plot that is updated in response to some form elements via an API call using jQuery's

$.getJSON()
. The data returned from the API call looks like:

{
"x-axis": ["2016-09-01", "2016-09-02", "2016-09-03", "2016-09-04", "2016-09-05", "2016-09-06", "2016-09-07", "2016-09-08", "2016-09-09", "2016-09-10", "2016-09-11", "2016-09-12", "2016-09-13", "2016-09-14", "2016-09-15", "2016-09-16", "2016-09-17", "2016-09-18", "2016-09-19", "2016-09-20", "2016-09-21", "2016-09-22", "2016-09-23", "2016-09-24", "2016-09-25", "2016-09-26", "2016-09-27", "2016-09-28", "2016-09-29", "2016-09-30"],
"Label 1": [35.0, 35.0, 35.0, 35.0, 35.0, 35.0, 35.0, 35.0, 35.0, 35.0, 35.0, 35.0, 35.0, 35.0, 35.0, 35.0, 35.0, 35.0, 35.0, 35.0, 35.0, 35.0, 35.0, 35.0, 35.0, 35.0, 35.0, 35.0, 35.0, 35.0],
"Label 2": [124.0, 124.0, 124.0, 124.0, 124.0, 124.0, 124.0, 124.0, 124.0, 124.0, 124.0, 124.0, 124.0, 124.0, 124.0, 124.0, 124.0, 124.0, 124.0, 124.0, 124.0, 124.0, 124.0, 124.0, 124.0, 124.0, 124.0, 124.0, 124.0, 124.0]
}


The plot is created like so:

ts = c3.generate({
bindto: "#timeseries",
data: {
x: "x-axis",
json: data
},
axis: {
x: {
type: "timeseries",
tick: {
format: function(x) {
return ts_date_format(x);
}
}
}
}
});


One of the options allows switching from daily view (one plot point per-day for each label for one month) to a monthly view (one plot point per month for each label for one year), upon which a new API request is made, returning new values for "x-axis":

{
"x-axis": ["2015-10-01", "2015-11-01", "2015-12-01", "2016-01-01", "2016-02-01", "2016-03-01", "2016-04-01", "2016-05-01", "2016-06-01", "2016-07-01", "2016-08-01", "2016-09-01"],
"Label 1": [2854.0, 4509.0, 5895.0, 6932.0, 4143.0, 3076.0, 1880.0, 1454.0, 1098.0, 1016.0, 1004.0, 1048.0],
"Label 2": [8680.0, 15090.0, 25079.0, 23746.0, 18096.0, 16058.0, 17610.0, 9269.0, 2550.0, 2852.0, 2232.0, 3720.0]
}


The data is loaded fine, like so:

ts.load({
unload: true,
json: data
});


But the x axis of the plot is not updated to use the new "x-axis" values returned. The existing daily view values are reformatted into the monthly format by the
ts_date_format()
function referenced above.

http://c3js.org/reference.html#api-x looks promising, and it actually does work, sometimes. This:

ts.x(data["x-axis"]);
ts.load({
unload: true,
json: data
});


does in fact update the x axis values, but raises a large number of the d3 error
<rect> attribute x: Expected length, "NaN"
. Reversing the order of the calls to
load()
and
x()
does not work, however, and does not raise an error:

ts.load({
unload: true,
json: data
});
ts.x(data["x-axis"]);


The
axes
argument to
load()
also seems like it might be appropriate http://c3js.org/reference.html#api-load, the docs say:

If axes given, the axes specifed by data.axes will be updated. axes must be Object that has target id as keys.


but that is a bit unclear to me. I've tried lots of variations similar to:

ts.load({
unload: true,
json: data,
axes: {
"x": data["x-axis"]
}
});


and

data["axes"] = {
"x": data["x-axis"]
}
ts.load({
unload: true,
json: data,
axes: {
"x": true
}
});


but they all fail to update the x axis values.

I am using c3.js version 0.4.11

solution

Thanks to duderoot below, I found the solution:

var cols = [];
for (var k in data) {
cols.push([k].concat(data[k]));
}
ts.load({
columns: cols
});

Answer

Hi I just remember that I recently played with this so here is a JSFiddle that do what you want. https://jsfiddle.net/duderoot/vwwod780/ here is the function that I use to update the x lables

setTimeout(function () {
chart.load({
    columns: [
        ["x", "2015-10-01", "2015-11-01", "2015-12-01", "2016-01-01", "2016-02-01", "2016-03-01", "2016-04-01"],
    ["Label 1", 2854.0, 4509.0, 5895.0, 6932.0, 4143.0, 3076.0, 1880.0, 1454.0, 1098.0, 1016.0, 1004.0, 1048.0],
    ["Label 2", 8680.0, 15090.0, 25079.0, 23746.0, 18096.0, 16058.0, 17610.0, 9269.0, 2550.0, 2852.0, 2232.0, 3720.0]

    ]
});

}, 3000);

Hope it helps, cheers

Comments