Dismiss
Announcing Stack Overflow Documentation

We started with Q&A. Technical documentation is next, and we need your help.

Whether you're a beginner or an experienced developer, you can contribute.

Sign up and start helping → Learn more about Documentation →

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.

share|improve this question

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

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.