Search code examples
javascriptjqueryhighcharts

Highcharts update x-axis categories dynamically


i'm looking for help with updating the x-axis categories on a Highcharts chart with periodically received data.

The chart is defined in a file called forecastgraph.html. It is loaded to index.php, the webpage where I want it displayed, by means of <?php require("widget/forecastgraph.html"); ?>. The chart renders as expected.

Live data which is handled via a js script (called mqtt.js) that receives incoming mqtt data in json format and using jquery updates various parts of index.php in this way: $("#elementid").html(a.b.c);. I load mqtt.js in the head of index.php using <script src="./js/mqtt.js"></script> This again works flawlessly.

What I am struggling with is how to pass incoming data from mqtt.js to the chart to update it as new data comes in. Specifically, I am trying to update the xAxis categories and the corresponding value pairs. Periodically, mqtt.js receives a new weather forecast and so the xAxis categories need to be updated with the new time period that the forecast applies to and the data needs to be updated to reflect the new high and low temperatures for the respective forecast periods.

The code for the chart is posted below. Any help would be appreciated.

Baobab

<script type="text/javascript">

$(function () {

    $('#forecastgraph').highcharts({

        chart: {
            type: 'columnrange',
        backgroundColor: 'rgba(0,0,0,0)',
        borderWidth: 0,
        margin: [12, 6, 36, 20]
        },

        title: {
            text: null,
        },

        exporting: {
            enabled: false
        },
        credits: {
            enabled: false
        },

        xAxis: {
            categories: [1,2,3,4],
        labels: {
            y: 30,
                style: {
                    color: 'white',
                    fontSize: '10px',
                    fontWeight: 'bold'
                }
            }
        },
        yAxis: {
            title: {
                enabled: false,
                x: -14,
            },
        labels: {
            align: 'left'
        },
        maxPadding: 0.5,
        plotLines: [{
        value: 10, //normmax
        width: 2,
        color: '#FF0000'
        },{
        value: 2, //normmin
        width: 2,
        color: '#009ACD'
        }]
        },

        tooltip: {
            enabled: false
        },

        plotOptions: {
            columnrange: {
                dataLabels: {
                    enabled: true,
                    style: {
                        textOutline: 'none'
                    },
                    crop: false,
                    overflow: 'none',
                    formatter: function () {
                        var color = this.y === this.point.high ? '#33C4FF' : 'red';
                        return '<span style="font-size: 12px; font-family:helvetica; font-weight:normal; text-shadow: none; color:' + color + '">' + this.y + '°</span>';
                        }
                }
            }
        },

        legend: {
            enabled: false
        },

        series: [{
            name: 'Temperatures',
            data: [
                [20, -3],
                [5, -2],
                [6, -2],
                [8, -15]
            ],
        color: '#b9deea',
        borderColor: '#92cbde',
        borderRadius: 4
        }]

    });

});

</script>

EDIT: Additional Information.

The incoming json data looks like this:

[{
    "period": "Monday",
    "condition": "Cloudy",
    "high_temperature": "7",
    "low_temperature": "-2"
    "icon_code": "10",
    "precip_probability": "20"
}, {
    "period": "Tuesday",
    "condition": "A mix of sun and cloud",
    "high_temperature": "6",
    "low_temperature": "-2"
    "icon_code": "02",
    "precip_probability": "20"
}, {
    "period": "Wednesday",
    "condition": "A mix of sun and cloud",
    "high_temperature": "3",
    "low_temperature": "-5"
    "icon_code": "02",
    "precip_probability": "20"
}, {
    "period": "Thursday",
    "condition": "A mix of sun and cloud",
    "high_temperature": "1",
    "low_temperature": "-10"
    "icon_code": "02",
    "precip_probability": "20"
}]

The function responsible for the incoming json formatted data in the mqtt.js script loaded to index.php handles the incoming data in this way (mqtt.js is started when index.php is loaded):

function onMessageArrived(message) {
    console.log("onMessageArrived: " + message.payloadString);
    //Env Canada forecast
    if (message.destinationName == "myHome/ec/json_data_ec") {
        var data = JSON.parse(message.payloadString);
        $("#forecast_period_1").html(data[0].period); // update div forecast_period_1 in index.php for debugging purposes and show that data is coming in
        forecast_period_1 = (data[0].period); // assign to global var
        forecast_period_1_high = (data[0].high_temperature); // global var
        forecast_period_1_low = (data[0].low_temperature); // global var

Updating various html elements throughout index.php with the incoming data works great and is stable. What I have attempted to do, but with no success, is to update the chart using the data placed in the global variables (declared as global at he beginning of the script) by the mqtt.js script. In the example above, forecast_period_1 needs to be used as the first of the four xAxis categories and forecast_period_1_high and forecast_period_1_low, to update the respective hi and lo values in the chart's data.


Solution

  • Is this an output that you want to achieve? In the below demo, I wrote a function that takes a high and low temperatures value and next is triggered on the button. The new data is attached to the chart via using the series.update feature.

    Demo: https://jsfiddle.net/BlackLabel/he768cz3/

    API: https://api.highcharts.com/class-reference/Highcharts.Series#update