2014-09-05 41 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);