Reload chart data via JSON with Highcharts

157,819

Solution 1

EDIT: The response down below is more correct!

https://stackoverflow.com/a/8408466/387285

http://www.highcharts.com/ref/#series-object

HTML:

<SELECT id="list">
<OPTION VALUE="A">Data Set A
<OPTION VALUE="B">Data Set B
</SELECT>
<button id="change">Refresh Table</button>

<div id="container" style="height: 400px"></div>

Javascript:

var options = {
    chart: {
        renderTo: 'container',
        defaultSeriesType: 'spline'
    },
    series: []
};

$("#change").click(function() {
    if ($("#list").val() == "A") {
        options.series = [{name: 'A', data: [1,2,3,2,1]}]
        // $.get('/dough/includes/live-chart.php?mode=month'
    } else {
        options.series = [{name: 'B', data: [3,2,1,2,3]}]
        // $.get('/dough/includes/live-chart.php?mode=newmode'
    } 

    var chart = new Highcharts.Chart(options);    
});

This is a very simple example since I don't have my files here with me but the basic idea is that every time the user selects new options for the stuff they want to see, you're going to have replace the .series data object with the new information from your server and then recreate the chart using the new Highcharts.Chart();.

Hope this helps! John

EDIT:

Check this out, its from something I've worked on in the past:

$("table#tblGeneralInfo2 > tbody > tr").each(function (index) {
    if (index != 0) {
        var chartnumbervalue = parseInt($(this).find("td:last").text());
        var charttextvalue = $(this).find("td:first").text();
        chartoptions.series[0].data.push([charttextvalue, chartnumbervalue]);
    }
});

I had a table with information in the first and last tds that I needed to add to the pie chart. I loop through each of the rows and push in the values. Note: I use chartoptions.series[0].data since pie charts only have 1 series.

Solution 2

The other answers didn't work for me. I found the answer in their documentation:

http://api.highcharts.com/highcharts#Series

Using this method (see JSFiddle example):

var chart = new Highcharts.Chart({
    chart: {
        renderTo: 'container'
    },

    series: [{
        data: [29.9, 71.5, 106.4, 129.2, 144.0, 176.0, 135.6, 148.5, 216.4, 194.1, 95.6, 54.4]        
    }]
});

// the button action
$('#button').click(function() {
    chart.series[0].setData([129.2, 144.0, 176.0, 135.6, 148.5, 216.4, 194.1, 95.6, 54.4, 29.9, 71.5, 106.4] );
});

Solution 3

You need to clear the old array out before you push the new data in. There are many ways to accomplish this but I used this one:

options.series[0].data.length = 0;

So your code should look like this:

options.series[0].data.length = 0;
$.each(lines, function(lineNo, line) {
                    var items = line.split(',');
                    var data = {};
                    $.each(items, function(itemNo, item) {
                        if (itemNo === 0) {
                            data.name = item;
                        } else {
                            data.y = parseFloat(item);
                        }
                    });
                    options.series[0].data.push(data);
                });

Now when the button is clicked the old data is purged and only the new data should show up. Hope that helps.

Solution 4

Actually maybe you should choose the function update is better.
Here's the document of function update http://api.highcharts.com/highcharts#Series.update

You can just type code like below:

chart.series[0].update({data: [1,2,3,4,5]})

These code will merge the origin option, and update the changed data.

Solution 5

Correct answer is:

$.each(lines, function(lineNo, line) {
                    var items = line.split(',');
                    var data = {};
                    $.each(items, function(itemNo, item) {
                        if (itemNo === 0) {
                            data.name = item;
                        } else {
                            data.y = parseFloat(item);
                        }
                    });
                    options.series[0].data.push(data);
                    data = {};
                });

You need to flush the 'data' array.

data = {};
Share:
157,819

Related videos on Youtube

NightMICU
Author by

NightMICU

Founder and CEO of Ophelia Design, a small web development firm in the Northern Neck of Virginia. I work mostly with PHP and the Laravel framework, Node, Python, Rails, LAMP stack, HTML5, Javascript, and jQuery.

Updated on August 10, 2020

Comments

  • NightMICU
    NightMICU over 3 years

    I am trying to reload the data for a Highcharts chart via JSON based on a button click elsewhere in the page. Initially I would like to display a default set of data (spending by category) but then load new data based on user input (spending by month, for example). The easiest way I can think of to output the JSON from the server is by passing a GET request to the PHP page, for example $.get('/dough/includes/live-chart.php?mode=month', retrieving this value from the button's ID attribute.

    Here is what I have so far to retrieve the default data (spending by category). Need to find how to load completely different data into the pie chart, based on user input, on demand:

    $(document).ready(function() {
                //This is an example of how I would retrieve the value for the button
                $(".clickMe").click(function() {
                    var clickID = $(this).attr("id");
                });
                var options = {
                    chart: {
                        renderTo: 'graph-container',
                        margin: [10, 175, 40, 40]
                    },
                    title: {
                        text: 'Spending by Category'
                    },
                    plotArea: {
                        shadow: null,
                        borderWidth: null,
                        backgroundColor: null
                    },
                    tooltip: {
                        formatter: function() {
                            return '<b>'+ this.point.name +'</b>: $'+ this.y;
                        }
                    },
                    credits: {
                        enabled: false
                    },
                    plotOptions: {
                        pie: {
                            allowPointSelect: true,
                            cursor: 'pointer',
                            dataLabels: {
                                enabled: true,
                                formatter: function() {
                                    if (this.y > 5) return '$' + this.y;
                                },
                                color: 'white',
                                style: {
                                    font: '13px Trebuchet MS, Verdana, sans-serif'
                                }
                            }
                        }
                    },
                    legend: {
                        layout: 'vertical',
                        style: {
                            left: 'auto',
                            bottom: 'auto',
                            right: '50px',
                            top: '100px'
                        }
                    },
                    series: [{
                        type: 'pie',
                        name: 'Spending',
                        data: []
                    }]
                };
                $.get('/dough/includes/live-chart.php', function(data) {
                var lines = data.split('\n');
                $.each(lines, function(lineNo, line) {
                    var items = line.split(',');
                    var data = {};
                    $.each(items, function(itemNo, item) {
                        if (itemNo === 0) {
                            data.name = item;
                        } else {
                            data.y = parseFloat(item);
                        }
                    });
                    options.series[0].data.push(data);
                });
                // Create the chart
                var chart = new Highcharts.Chart(options);
            });
            });
    

    Any help would be greatly appreciated

    EDIT

    Here is the updated Javascript thanks to Robodude. John, you have me on the right track here - thanks! I'm now getting stuck with how to replace the data on the chart from the AJAX request. I must admit that the code following the $.get() is most likely from sample code, I do not fully understand what is going on when it is run - perhaps there is a better way to format the data?

    I was able to make some progress in that the chart now loads new data but it is added on top of what is already there. I suspect that the culprit is this line:

    options.series[0].data.push(data);
    

    I tried options.series[0].setData(data); but nothing happens. On the bright side, the AJAX request works flawlessly based on the value of the select menu and there are no Javascript errors. Here is the code in question, sans chart options:

    $.get('/dough/includes/live-chart.php?mode=cat', function(data) {
                var lines = data.split('\n');
                $.each(lines, function(lineNo, line) {
                    var items = line.split(',');
                    var data = {};
                    $.each(items, function(itemNo, item) {
                        if (itemNo === 0) {
                            data.name = item;
                        } else {
                            data.y = parseFloat(item);
                        }
                    });
                    options.series[0].data.push(data);
                });
                // Create the chart
                var chart = new Highcharts.Chart(options);
            });
            $("#loadChart").click(function() {
                var loadChartData = $("#chartCat").val();
                    $.get('/dough/includes/live-chart.php?mode=' + loadChartData, function(data) {
                    var lines = data.split('\n');
                    $.each(lines, function(lineNo, line) {
                        var items = line.split(',');
                        var data = {};
                        $.each(items, function(itemNo, item) {
                            if (itemNo === 0) {
                                data.name = item;
                            } else {
                                data.y = parseFloat(item);
                            }
                        });
                        options.series[0].data.push(data);
                    });
                    // Create the chart
                    var chart = new Highcharts.Chart(options);
                });
            });
        });
    

    EDIT 2 This is the format that the chart is pulling from - very simple, category name and value with \n after each.

    Coffee, 4.08
    Dining Out, 5.05
    Dining: ODU, 5.97
    Dining: Work, 38.41
    Entertainment, 4.14
    Gas, 79.65
    Groceries, 228.23
    Household, 11.21
    Misc, 12.20
    Snacks, 20.27
    
  • RoboKozo
    RoboKozo over 13 years
    I took the code I wrote and put it up on jsfiddle for your convenience: jsfiddle.net/EmMxH
  • RoboKozo
    RoboKozo over 13 years
    Hey again NightMICU! I'm sorry I don't have much time to explain whats going on but check this out: jsfiddle.net/w4DKf What is the format of the data that is coming back? Just remember that each value for your pie chart is part of an array that is part of the highcharts data array which is a part of the series array!
  • NightMICU
    NightMICU over 13 years
    John, I think that perhaps the issue here is the format of the chart data. It is not JSON and I am guessing it needs to be? If I change the output from the PHP file to JSON, how would I include that to the Javascript?
  • RoboKozo
    RoboKozo over 13 years
    It doesn't have to be returned in JSON format for it to work. It's just that jquery can automatically format JSON strings into objects that can be accessed very easily. Otherwise we will have to parse your data manually. If formatting in JSON is easily possible, I'd recommend it!
  • NightMICU
    NightMICU over 13 years
    Thanks again, John. I just added a comment to my question with a link to exactly what I'm working with. I'm throwing in the towel tonight but tomorrow I'm going to see if I can change the PHP output to JSON.
  • RoboKozo
    RoboKozo over 13 years
    Figured it out using your code :) Thanks for putting it up there. The line you questioned was indeed the culprit and the solution to it wasn't too difficult. After the loadchart button is clikced all you have to do is clear out the data array using => options.series[0].data = [];
  • Tobias Sarnow
    Tobias Sarnow over 12 years
    This solution is even bedder because only updated values will be changed and nothing more. Example here: jsfiddle.net/ebuTs/16
  • John Hargrove
    John Hargrove over 12 years
    The proper way to do this is by using the chart.series[0].setData(...) function which will efficiently update the data and optionally redraw the chart for you. Recreating the chart object over and over will leak memory and eventually your webpage will start running -terrible-.
  • John Hargrove
    John Hargrove over 12 years
    +1 This is the proper approach ... The chosen answer involves recreating the Chart object every time a change is made and is very inefficient.
  • NightMICU
    NightMICU almost 12 years
    For my purposes, this did not work at all and actually made a client get upset with me. The data I am trying to display is Call Statistics for a local rescue squad. Each month, they run a different number of calls in different categories - so it is not always the same every month (for example, they might not run a single car accident one month, 10 the next). Your answer caused odd behavior, including missing categories and the error "a is undefined" in the HighCharts code. The selected answer may be inefficient in some ways but it works and the client is happy.
  • BentOnCoding
    BentOnCoding over 10 years
    What if I have multiple series of data ? This seems like a very specific answer that isn't really useful to many scenarios
  • nilskp
    nilskp over 10 years
    At the very least call Chart.destroy() before creating a new one. Otherwise you'll run out of memory eventually. Been there, done that.
  • crashtestxxx
    crashtestxxx over 10 years
    After 2 hours of trying to figuring out, why my scatter plot was stacking serries on each call. I have finally found this fix. You have saved my rest of the day. It worked. Thank you.
  • lababidi
    lababidi almost 10 years
    series[0], series[1], series[2] represent all 3 of your series. You can generalize it to: series.forEach(function(s, index){s.setData(newData[index])})

Related