Search code examples
angularjsflotangularjs-service

Flotcharts not rendering with angularjs


I am having issues rendering Flotcharts with data populated from an AngularJS (v1.2.5) service call. When the data is hard-coded, the charts render as expected but not when assigned the value from a $resource call (console logging shows "undefined" as the value).

The odd thing is that the same variable I use to populate the chart data is displayed in the view and works fine which makes me think this could be some sort of race condition or scoping issue.

I have tried assigning the the $scope variables as a result of resolved promises without success to remedy race conditions as well as tried things such as $scope.$apply() from the chart directive.

Below are code excerpts from my application. Any help is appreciated. Thank you.

HTML wrapper:

<!DOCTYPE html>
<html data-ng-app="app" data-ng-controller="app">
    <head>
        <title>FlotChart Example</title>
    </head>

    <body>
        <main data-ng-view></main>
    </body>
</html>

Template from Overview route:

<div class="chart-title">{{getCount.count}} Total Transactions</div>
<div id="deposits" data-chart="pie" data-flot-chart data-ng-model="model" data-ng-controller="OverviewCtrl"></div>

Main Module ("app"):

;(function (angular) {
    'use strict';

    angular.module('app', ['ngRoute', 'ngResource', 'ngTouch', 'services.Localization', 'Login', 'Overview'])
        .config(['$routeProvider', function ($routeProvider) {
            $routeProvider
            .when('/', {
                templateUrl: 'views/login.html',
                controller: 'LoginCtrl'
            })
            .when('/overview', {
                templateUrl: 'views/overview.html',
                controller: 'OverviewCtrl'
            })
            .otherwise({
                redirectTo: '/'
            });
        }])

        .controller('App', ['$rootScope', 'Localize', function ($rootScope, Localize) {
            // initialize localization
            $rootScope.labels = Localize.get();
        }]);
}(angular));

Overview Controller (used in charts and view):

;(function (angular) {
    'use strict';

    angular.module('Overview', ['services.DepositsSvc'])

        .controller('OverviewCtrl', ['$rootScope', '$scope', 'DepositCount', 'DepositCountGET', function ($rootScope, $scope, DepositCount, DepositCountGET) {

            $scope.getCount = DepositCount.get();

            $scope.getGETCount = DepositCountGET.get();

            $scope.model = {};

            $scope.model.data = [
                {
                    label: $rootScope.labels.gets,
                    data: $scope.getGETCount.count,
                    color: "#e4d672"
                },
                {
                    label: $rootScope.labels.puts,
                    data: $scope.getCount.count,
                    color: "#c2cfeb"
                }
            ];

            $scope.model.options = {
                series: {
                    pie: {
                        show: true,
                        radius: 1,
                        label: {
                            radius: 2/3,
                            formatter: function (label, series) {
                                return '<div class="pie">' + label + ': ' +
                                    series.data[0][1] + '<br>(' + Math.round(series.percent) + '%)</div>';
                            }
                        }
                    }
                },
                legend: {
                    show: false
                }
            };
        }]);
}(angular));

Services (output from both calls is { count: number }):

;(function (angular) {
    'use strict';

    angular.module('services.DepositsSvc', ['ngResource', 'ngRoute'])

        .factory('DepositCount', ['$resource', function ($resource) {
            return $resource('/rest/deposits/count', {}, {
                query: { method: 'GET', params: {}, isArray: true }
            });
        }])

        .factory('DepositCountGET', ['$resource', function ($resource) {
            return $resource('/rest/deposits/countgetdeposits', {}, {
                query: { method: 'GET', params: {}, isArray: true }
            });
        }]);
}(angular));

Charts directive:

;(function (angular, $) {
    'use strict';

    angular.module('directives.FlotCharts', [])

        .directive('flotChart', function () {
            return {
                restrict: 'EA',
                controller: ['$scope', '$attrs', function ($scope, $attrs) {
                    var plotid = '#' + $attrs.id,
                        model = $scope[$attrs.ngModel];

                    $scope.$watch('model', function (x) {
                        $.plot(plotid, x.data, x.options);
                    });
                }]
            };
        });
}(angular, jQuery));

Solution

  • Solution documented at AngularJS Google Group.