I think I can code
I think I can code

Reputation: 647

Highcharts series data not persisting through angular route change

I'm using Highcharts with AngularJS. I have a directive which generates the chart. In the link function I specify a default object chartOptions. After setting the default options, I append that object to another object passed to the directive which persists between routes and refreshes, passedObject. Thus any changes to chartOptions after being appended successfully persist. Then the chart generates with the call to Highcharts.chart();

return {
    restrict: 'E',
    scope: {
        passedObject: "="
    },
    link: function (scope, element) {

        var chartOptions = {
            title : {
             text: 'sample report'
            }
            ...
        }

        scope.passedObject.chartOptions = scope.passedObject.chartOptions || chartOptions;

        var chart = Highcharts.chart(element[0], scope.passedObject.chartOptions);
    }

    // successfully add new series
    // series rendered immediately but does not persist though view changes and page reload.
    scope.addSeries = function(seriesObject){
        scope.elementObject.chart.addSeries(seriesObject);
    };

    // successfully pushes object to array
    // does not immediately render because Highchart doesn't see change 
    // but does render after reloading because Highchart checks options again
    // Does not render with animation like addSeries() API does.
    scope.addSeriesNoAPI = function(seriesObject){
       scope.elementObject.chart.series.push(seriesObject);
    };
}

There is no issue generating the chart the first time, and if I return to this view, the chart generates again with the same default options.

However, if I use the Highcharts API to programatically add a new data series chart.addSeries(newSeriesObject) the series is added and renders on the chart, but will not persist between routes and refreshes.

If I manually add the series object to my chartOptions via straight JS scope.passedObject.chartOptions.series.push(newSeriesObject) the object is successfully pushed to the array and will persist, but the chart will not automatically update because it doesn't know the series array changed, which is clearly why the API exists.

Upon closer inspection, it appears that Highchart's addSeries() function is pushing the new object to some array other than the one I am persisting, but I can't figure out how to get this to work.

I assumed that this line of code: var chart = Highcharts.chart(element[0], scope.passedObject.chartOptions); would bind the chart to the scope.passedObject.chartOptions object, such that when something like the addSeries() function added a new series, it would be added into scope.passedObject.chartOptions. After logging and watching objects, however that does not appear to be the case.

Upvotes: 1

Views: 766

Answers (1)

Arathi Sreekumar
Arathi Sreekumar

Reputation: 2574

One way is to hold that data in the root scope (but that is not the best way).

Another is to use angular service to store this data. And include this service where you need it.

An angular service unlike controllers will not get reset when changing views/pages.

I would suggest that you create an angular service that stores the chart options, which has a chart options object and a getter and a setter. You could also hold the functions that make changes to the chartobject in this service.

In your case you seem to do manipulations to the chart object within the controller (after you are getting it from a service perhaps?), if so you will have to set the new object back to the service.

Also when I say service I mean something like this:

app.service('highChartService', function() {
  var chartOptions;
  var highChartServiceObj = {};

  highChartServiceObj.getChartOptions = function() {
      return chartOptions;
  };

  highChartServiceObj.setChartOptions = function (options) {
     chartOptions = options;
  };

  highChartServiceObj.computeChartObject = function () {
    //do some computation
  }

  return highChartServiceObj;

});

Add the above service to your directive and use that to update your highchart object when any changes are made.

Also if I am not wrong what you would like to do is add newseriesobject like this chart.addSeries(newSeriesObject) which solves your highchart dilemma. Why not then update your chart object as the next step: scope.passedObject.chartOptions.series.push(newSeriesObject)? Though I would rather that be part of the service too if I was doing this, all of the highchart manipulations would just be a part of the service, where I would have a function like this in above service:

highChartServiceObj.updateChart(newSeriesObject, chart) {
   chartOptions.series.push(newSeriesObject);
   chart.addSeries(newSeriesObject);
}

Upvotes: 1

Related Questions