madhusudhan
madhusudhan

Reputation: 337

angularjs morris directive to create charts from a json rest

I've created a directive for plotting bar charts with Morris. It does plot the bar charts when I hard code the values. But I'm not able to plot the charts with values received from an http response. I'm new to javascript, angularjs etc.

Module:

var sampleApp = angular.module('sample',[]);

Directive:

sampleApp.directive('barchart', function() {

    return {
        restrict: 'E',
        template: '<div></div>',
        replace: true,
        link: function($scope, element, attrs) {

            var data = $scope[attrs.data],
                xkey = $scope[attrs.xkey],
                ykeys= $scope[attrs.ykeys],
                labels= $scope[attrs.labels];

            var setData = function(){
                console.log('inside setData function');
                Morris.Bar({
                    element: element,
                    data: data,
                    xkey: xkey,
                    ykeys: ykeys,
                    labels: labels
                });
            };

            // The idea here is that when data variable changes, 
            // the setData() is called. But it is not happening.
            attrs.$observe('data',setData);
        }

    };

});

Controller:

sampleApp.controller('sampleController',function($scope, $http){

  $scope.xkey = 'range';

  $scope.ykeys = ['total_tasks',     'total_overdue'];

  $scope.labels = ['Total Tasks', 'Out of Budget Tasks'];

  $scope.myModel = [
    { range: 'January', total_tasks: 5, total_overdue: 5 },
    { range: 'January', total_tasks: 35, total_overdue: 8 },
    { range: 'January', total_tasks: 20, total_overdue: 1 },
    { range: 'January', total_tasks: 20, total_overdue: 6 }
  ];

  $http({method: 'GET', url: '../test/executeTest'}).
    success(function(data, status, headers, config) {
    // here I would populate myModel with values from above url. 
    // But for simplicity, I'm just hardcoding the values(changed slightly) again.
    $scope.myModel = [
    // changing just one value in first row.
    { range: 'January', total_tasks: 25, total_overdue: 5 },
    { range: 'January', total_tasks: 35, total_overdue: 8 },
    { range: 'January', total_tasks: 20, total_overdue: 1 },
    { range: 'January', total_tasks: 20, total_overdue: 6 }
  ];
    console.log('success ' + $scope.myModel[0].total_tasks);

    }).
    error(function(data, status, headers, config) {
        console.log('error');
    });
});

html:

<html>
<head>
<script src="lib/jquery-1.8.2.min.js"></script>
<script src="lib/angular.min.js"></script>
<script src="lib/raphael-min.js"></script>
<script src="lib/morris.min.js"></script>
<meta charset=utf-8 />
<title>JS Bin</title>

</head>
<body ng-app="sample" ng-controller="sampleController">

  <barchart xkey="xkey" ykeys="ykeys" labels="labels" data="myModel"></barchart>
  </script>
</body>
</html>

I read somewhere that I should not be using observers if the value does not contain curly braces like {{..}}. But I don't know how to fix it with watchers or any other thing.

Upvotes: 1

Views: 3698

Answers (2)

YuriPiratello
YuriPiratello

Reputation: 21

answer https://stackoverflow.com/a/22063220/2266630 - $digest problem

replace $scope.$apply() for

$timeout(function(){
  $scope.$apply();
});

[1] - $timeout - https://coderwall.com/p/udpmtq

[2] - $apply - http://jimhoskins.com/2012/12/17/angularjs-and-apply.html

Upvotes: 1

madhusudhan
madhusudhan

Reputation: 337

I was able to resolve this issue. I added the below code to my directive:

$scope.$watch(function() {
  return $scope.myModel}, setData);

and added the below code to my controller after changing the scope.myModel

$scope.$apply();

After these changes, I see that the graph is updated with new values. But it gave an exception in the console:

Error: [$rootScope:inprog] http://errors.angularjs.org/1.2.13/$rootScope/inprog?p0=%24digest

Anyway, since it shows me the output I want, it unblocked me for now.

Upvotes: 0

Related Questions