2014-09-05 69 views
2

我正在使用带有角度的Morris图表来显示图形报告,其中数据通过其余API调用从我们的后端服务器中获取。重新加载角度指令以在API调用之后重绘morris.js图表​​

我能够在控制台日志中看到检索到的数据,但它不显示在图表中。我发现指令条形图在api调用之前被加载,因此显示$ scope.myModel中可用的数据。

我试图找到是否有某种角度的方式,可以帮助我重新加载指令时,从API调用收到数据。有人可以帮助我吗?

条形图从代码生成:

enter image description here

这里是我的代码

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

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

return { 

    // required to make it work as an element 
    restrict: 'E', 
    template: '<div></div>', 
    replace: true, 
    // observe and manipulate the DOM 
    link: function($scope, element, attrs) { 

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

     Morris.Bar({ 
       element: element, 
       data: data, 
       xkey: xkey, 
       ykeys: ykeys, 
       labels: labels 
      }); 

    } 

}; 

}); 

sampleApp.controller('sampleController',function($scope, $http){ 
$scope.values = [] 

$scope.xkey = 'range'; 

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

$scope.labels = ['Total Tasks', 'Out of Budget Tasks']; 
$http.get('http://api.*******.com/api/getAppID/?parameter=whatsapp').success(function(res) { 
     if(!res.error) { 
      if(res.status==1) res.status=true 
      else res.status=false 
    $scope.values[0] = res.metrices.total_shares 
    $scope.values[1] = res.metrices.unique_share_count 
    $scope.values[2] = res.metrices.total_clicks 
    $scope.values[3] = res.metrices.total_downloads 
} 
}) 
$scope.myModel = [ 
{ range: 'January', total_tasks: $scope.values[0], total_overdue: 5 }, 
{ range: 'January', total_tasks: $scope.values[1], total_overdue: 8 }, 
{ range: 'January', total_tasks: $scope.values[2], total_overdue: 1 }, 
{ range: 'January', total_tasks: $scope.values[3], total_overdue: 6 } 
]; 

}); 

HTML部分:

<!DOCTYPE html> 
<html> 
<head> 
    <link rel="stylesheet" href="http://cdn.oesmith.co.uk/morris-0.4.3.min.css"> 
    <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.1/jquery.min.js"></script> 
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.7/angular.min.js"></script> 
    <script src="//cdnjs.cloudflare.com/ajax/libs/raphael/2.1.0/raphael-min.js"></script> 
    <script src="http://cdn.oesmith.co.uk/morris-0.4.3.min.js"></script> 
    <script src="js/sample.js"></script> 
    <meta charset=utf-8 /> 

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

    <barchart xkey="xkey" ykeys="ykeys" labels="labels" data="myModel"></barchart> 


</body> 

+1

你可以添加在http://plnkr.co/,这样我们可以很容易地调试 – 2014-09-05 11:43:55

回答

4

你不需要的“标志”变量,您需要观看“基于myModel”来代替,而你并不需要创建一个新的莫里斯图表每次模式的转变,第二次模型改变了你只需要调用morris setData方法即可。

我开始自己的指令从你的开始,我结束了这个代码工作正常,重新绘制窗口大小事件的图表,也许有人可以使用它。

(function() { 
    'use strict'; 
    var module = angular.module('app.charts', []); 
    module.directive('areachart', function ($window) { 

     return { 
      restrict: 'E', 
      template: '<div></div>', 
      replace: true, 
      link: function ($scope, element, attrs) { 
       var morris; 
       angular.element($window).bind('resize', function() { 
        if (morris) { 
         console.log('morris resized'); 
         morris.redraw(); 
        } 
       }); 

       attrs.$observe('value', function (val) { 
        if (!morris) { 
         console.log('creating chart'); 
         morris = Morris.Area({ 
          element: element, 
          data: angular.fromJson(val), 
          xkey: $scope[attrs.xkey], 
          ykeys: $scope[attrs.ykeys], 
          labels: $scope[attrs.labels] 
         }); 
        } else { 
         console.log('setting chart values'); 
         morris.setData(angular.fromJson(val)); 
        } 
       }); 
      } 
     }; 
    }); 
}).call(this); 

HTML

<areachart xkey="xkey" ykeys="ykeys" labels="labels" data-value="{{myModel}}"></areachart> 

在你的控制器:

 $scope.xkey = 'y'; 

     $scope.ykeys = ['a', 'b']; 

     $scope.labels = ['Series A', 'Series B']; 

     $scope.myModel = [ 
       { y: '2006', a: 100, b: 90 }, 
       { y: '2007', a: 75, b: 65 }, 
       { y: '2008', a: 50, b: 40 }, 
       { y: '2009', a: 75, b: 65 }, 
       { y: '2010', a: 50, b: 40 }, 
       { y: '2011', a: 75, b: 65 }, 
       { y: '2012', a: 100, b: parseInt((Math.random() * 10000)/10) } 
+0

非常好的答案...帮了很多.. – gsk 2015-03-29 13:17:47

0

我已经很努力地试图解决这个问题。发布此答案以帮助其他同行编码人员。

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

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

return { 

    // required to make it work as an element 
    restrict: 'E', 
    template: '<div></div>', 
    replace: true, 
    // observe and manipulate the DOM 
    link: function($scope, element, attrs) { 
     $scope.$watch('flag', function() { 

    $scope.myModel = [ 
     { range: 'January', total_tasks: $scope.values[0], total_overdue: 5 }, 
     { range: 'January', total_tasks: $scope.values[1], total_overdue: 8 }, 
     { range: 'January', total_tasks: $scope.values[2], total_overdue: 1 }, 
     { range: 'January', total_tasks: $scope.values[3], total_overdue: 6 } 
    ]; 

    console.log($scope.flag + $scope.values+' The one we want watch') 

    $scope.xkey = 'range'; 

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

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

     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 
      }); 
      }; 
     if ($scope.flag == 1) {  
      attrs.$observe('data',setData) 
      }    
      }); 

    } 

}; 

}); 


sampleApp.controller('sampleController',function($scope, $http){ 
$scope.flag = 0; 
$scope.values = []; 



$http.get('http://api.*******/api/*****/?appname=whatsapp').success(function(res) { 
     if(!res.error) { 
      if(res.status==1) res.status=true 
      else res.status=false 

    $scope.values[0] = res.metrices.total_shares 
    $scope.values[1] = res.metrices.unique_share_count 
    $scope.values[2] = res.metrices.total_clicks 
    $scope.values[3] = res.metrices.total_downloads 
    $scope.flag = 1; 
    console.log($scope.flag+"in api call"+$scope.values) 

} 

}) 


}); 

这对我有效。 但是,如果我们删除$ watch中的(flag == 1)条件,它将重叠绘制2次图表。如果有人能改进这个答案,我将不胜感激。

此链接真的很有帮助。 [1]:http://angular-tips.com/blog/2013/08/watch-how-the-apply-runs-a-digest

0

为 “重绘” 所需要的唯一一件事就是调用$应用......这将调用$消化...这将检查是否有任何$观察者有(或没有)改变,如果是的话重绘/绘制对象。

setTimeout(function() { 
    $scope.$apply(function(){ 
    morris = Morris.Area({ 
     element: element, 
     data: angular.fromJson(val), 
     xkey: $scope[attrs.xkey], 
     ykeys: $scope[attrs.ykeys], 
     labels: $scope[attrs.labels] 
    }); 
    }); 
},1500);