36

I am new to Angular and Flot, but am experienced with Jquery and Javascript. I am a bit confused about how to go about binding a Flot chart to Angular data models, since Flot is a JQuery plugin. I've searched around, but haven't been able to find an example.

I would also be happy to use highcharts, google-charts, or any other charting solution.

0

2 Answers 2

66

Since charting involves heavy DOM manipulation, directives are the way to go.

Data can be kept in the Controller

App.controller('Ctrl', function($scope) {
    $scope.data = [[[0, 1], [1, 5], [2, 2]]];
});

And you can create a custom HTML tag1 specifying the model you want to get data from

 <chart ng-model='data'></chart>

which angular can compile through a directive

App.directive('chart', function() {
    return {
        restrict: 'E',
        link: function(scope, elem, attrs) {
            var data = scope[attrs.ngModel];
            $.plot(elem, data, {});
            elem.show();
        }
    };
});

Example here.

This process is similar for most plugins that modify the DOM.

-*-

Also, you can watch for changes in the chart's underlying data and redraw it, so this way you can grab data through the $http service from your controller and update the view automatically. This can be achieved by modifying the linking function in the directive definition object

   var chart = null,
       opts  = { };

    scope.$watch(attrs.ngModel, function(v){
        if(!chart){
            chart = $.plot(elem, v , opts);
            elem.show();
        }else{
            chart.setData(v);
            chart.setupGrid();
            chart.draw();
        }
    });

Notice the usage of Flot's API within the directive to achieve what we want.

Here the full example


1 Can be an attribute too.

Sign up to request clarification or add additional context in comments.

5 Comments

This was very informative. I had to learn a bit more about Angular's API to get it working across two separate js files (to keep the directive and the controller separate). I found one problem, which is that if you watch 'data', you have tied your directive to the model's name. A better solution is to use 'scope.$watch(attrs.ngModel',....). I have updated the fiddle here: jsfiddle.net/TDwGF/3
For new Angular users: To use this directive as an attribute, you need to change the line that says "restrict: 'E'" to "restrict: 'EA'". E is 'Element', A is 'Attribute'.
I suggest to use var data = scope.$eval(attrs.ngModel) in the first fiddle because then your ng-model can be "charts.exchangerates.eur2usd". In the second fiddle I would use a deep watch to see changes inside the data object. Here is a fiddle that is not broken due the MIME-Change in github: jsfiddle.net/dWDDp
Examples where not working I updated them with a cdn link instead of github user content.
Hello can you please see my question stackoverflow.com/questions/37256487/…
1

To use jQuery plugins with angularJS, you have to wrap them in directives, you can find some exemples of jQuery plugins directives by reading the source code of angularUI directives: https://github.com/angular-ui/angular-ui/tree/master/modules/directives

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.