Search code examples
angularjshighchartsmouseclick-event2-way-object-databinding

Click event and two way data binding in HighCharts using AngularJS


I'm trying to write a directive for HighCharts in AngularJS which supports two way data binding as well as click events on charts.

Directive:

app.directive('highchart', function () {
    return {
        restrict: 'E',
        template: '<div></div>',
        replace: true,
        link: function (scope, element, attrs) {
             scope.$watch(scope.example_chart, function() {
             var chart = JSON.parse(attrs.chart)
             element.highcharts(chart);
             }
        }
    }
});

Now, when I write my HTML like this:

<div>            
     <highchart chart='example_chart'></highchart>
</div>

It supports the click event, but not two way data binding.

And, when it is passed as an expression:

<div>            
     <highchart chart='{{example_chart}}'></highchart>
</div>

It supports two way data binding but the function written in JSON of example_chart for click event doesn't get parsed and hence not functioning.

So, suggest a way to handle both the cases in AngularJS way.


Solution

  • highcharts-ng

    You can use highcharts-ng directive, See usage here: Fiddle

    Also you can use custom directive:

    Custom

    See demo in Fiddle

    Actually there is nothing special here, pretty simple isolate scope directive with watcher on highChart configuration (defined as JSON).

    I my case I used several watchers on specific fields to improve perforamnce but you can run deep watch on all config object


    HTML

    <high-chart config="chartConfig"> </high-chart> 
    

    JS

    myapp.directive('highChart',
       function () {
           return {
               restrict: 'E',
               replace:true,
                scope: {
                config: '='  
               },
               template: '<div id="container" style="min-width: 310px; height: 400px; margin: 0 auto"></div>',
               link: function (scope, element, attrs) {
    
                    var chart = false;
    
                    var initChart = function() {
                      if (chart) chart.destroy();
                      var config = scope.config || {};
                      //var mergedOptions = getMergedOptions(scope, element, config);
                      chart = new Highcharts.Chart(config);
    
                      if(config.loading) {
                        chart.showLoading();
                      }
    
                    };
                    initChart();
    
    
           scope.$watch('config.loadRandomData', function (value) {
               if(value == false){return;}
    
               chart.series[0].setData(scope.config.series[0].data);          
    
               scope.config.loadRandomData = false;
            }, true);
    
    
            scope.$watch('config.loading', function (loading) {
              if(loading) {
                chart.showLoading();
              } else {
                chart.hideLoading();
              }
            });
    
           scope.$watch('config.series[0].type', function (type) {
    
             chart.series[0].update({type: type});        
            });
    
            scope.$watch('config.series[0].dataLabels.enabled', function (enableDataLabels) {          
             chart.series[0].update({dataLabels: {enabled: enableDataLabels}});        
            });                
             }//end watch           
           }
       }) ;
    

    enter image description here