Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how to Create AngularJS charts with dynamic data

Hi im trying having a webpage that displays the sentiments of tweets of politicians. I am trying to create a chart for the sentiment statistics. I am using Zingchart and i am able to create for static data but i am not able to create for dynamic data.

This is the code that i used to insert static data with array chartdata.

   <div class="row">
    <div class="col-sm-12">
      <div ng-init="chartdata = [[1167],[456],[990]]">
        <zingchart id="chart-1" zc-values="chartdata" zc-json="myJson" 
         zc-width="100%" zc-height="568px"></zingchart>
      </div>
    </div>
  </div>

static pie chart

It works fine like this but i want to use data from my angularjs instead of the static values. For example: Im trying to do something like this but it does not work

  <div class="row">
      <div class="col-sm-12">
        <div ng-init="chartdata =[[{{politicianData.stats.total_positive}}],[{{politicianData.stats.total_negative}}],[{{politicianData.stats.total_neutral}}]]">
          <zingchart id="chart-1" zc-values="chartdata" zc-json="myJson" zc-width="100%" zc-height="568px"></zingchart>
        </div>
      </div>
    </div>

How to get the data from the promise array data from the angular controller?

this is my politician-controller:

    angular.module('myapp')
    .controller('PoliticianController', function($scope, PoliticianData, Politician, searchService, utilService) {
var politicianData = new Politician(PoliticianData);

        politicianData.$promise.then(function (result) {

            $scope.politicianData = result;
  });
$scope.myJson = {
                            globals: {
                            shadow: false,
                            fontFamily: "Verdana",
                            fontWeight: "100"
                                        },
                                        type: "pie",
                                        backgroundColor: "#fff",

                                        legend: {
                                            layout: "x5",
                                            position: "50%",
                                            borderColor: "transparent",
                                            marker: {
                                                borderRadius: 10,
                                                borderColor: "transparent"
                                            }
                                        },
                                        tooltip: {
                                            text: "%v requests"
                                        },
                                        plot: {
                                            refAngle: "-90",
                                            borderWidth: "0px",
                                            valueBox: {
                                                placement: "in",
                                                text: "%npv %",
                                                fontSize: "15px",
                                                textAlpha: 1,
                                            }
                                        },
                                        series: [{
                                            text: "Positive",
                                            backgroundColor: "#FA6E6E",
                                        }, {
                                            text: "Negative",
                                            backgroundColor: "#D2D6DE"
                                        }, {
                                            text: "Neutral",
                                            backgroundColor: "#28C2D1"
                                        }]
                                    };

    });

And this is the politician.html page

<span>{{politician.first_name}} {{politician.last_name}}</span>
                    </td>
                    <td>{{politicianData.stats.total}}</td>
                    <td>{{politicianData.stats.twitter.total}}</td>
                    <td>{{politicianData.stats.rss.total}}</td>
                   <td>{{politicianData.stats.total_negative}}</td>
                   <td>{{politicianData.stats.total_positive}}</td>
                   <td>{{politicianData.stats.total_neutral}}</td>

PoliticianData.stats.total_positive displays the count correctly and i want to use the same data as input values to my chart. How do I do that?

like image 792
Cocoa Avatar asked Jul 26 '16 11:07

Cocoa


2 Answers

Full disclosure, I'm a member of the ZingChart team.

This exact functionality you are looking for is data binding. We have documentation on our angularjs-charts page for data binding elements to the chart.

In your case there are a few steps need to achieve what you want. My first suggestion would be to take unnecessary controller logic out of your view in the ng-init and keep it inside the directive. Just a suggestion, not necessary. For the sake of this answer my format will keep most everything inside the controller.

HTML:

<body ng-app="myApp">
  <div ng-controller="MainController">
    <div zingchart id="chart-1" zc-json="myJson" zc-width="100%" zc-height="568px" zc-values="aValues"></div>
  </div>
</body>

App Logic:

var app = angular.module('myApp',['zingchart-angularjs']);

app.controller('MainController', function($scope, $timeout) {

// mimick your promise
(function(){
  $scope.data = {};
  $scope.data.valuesOne = [1,2,3,4,5];
  $scope.data.valuesTwo = [1,2,3,4,5];
  $scope.aValues = [$scope.data.valuesOne,$scope.data.valuesTwo];
})();

$scope.myJson = {
  type : "bar",
  title:{
    backgroundColor : "transparent",
    fontColor :"black",
    text : "Hello world"
  },
  backgroundColor : "white",
  series : [
    {
      backgroundColor : '#00baf2'
    },
    {
      backgroundColor : '#4caf4f'
    }
  ]
};

 // automatically wraps code in $apply
 $timeout(function(){

   // wont reflect changes in aValues because its an object
   $scope.data.valuesOne = [5]; 

   // must force the reflection of the changes
   $scope.aValues = [$scope.data.valuesOne, $scope.data.valuesTwo];

   // will reflect changes with one line, not the above two lines
   //$scope.aValues[0] = [5];

 },1500);

});

You can see that I have set a $timeout to reflect graph changes after a 1.5 seconds. This $timeout is to mimic some sort of object change from a DB update. There are two ways to update the values but to see why we must first learn more about the ZingChart Angular directive.

You must use zc-values in HTML and not just zc-json because the code has a deep equality watch on zc-values by using $watchCollection().

"The $watchCollection() function is a sort-of mid-ground between the two $watch() configurations above. It's more in-depth than the vanilla $watch() function; but, it's not nearly as expensive as the deep-equality $watch() function. Like the $watch() function, the $watchCollection() works by comparing physical object references; however, unlike the $watch() function, the $watchCollection() goes one-level deep and performs an additional, shallow reference check of the top level items in the collection." -referenced here.

Thats why it'll only work in my example when I change references in the aValues array.

You can see that inside the $timeout there are two ways to update the values of the chart. Because you have an array of arrays making changes to the inner arrays wont be reflected because they are deep object properties. You can see updating a single array must be force assigned back into the parent to reflect the change. A change on the parent directly will update the reference and will reflect changes in one line.

Codepen demo here.

More Angular/ZingChart Links

  1. Angular Page
  2. ZingChart Codepen
like image 140
nardecky Avatar answered Oct 17 '22 14:10

nardecky


  • Create a service with factory
  • Call that service for data
  • Use only zingchart directive
  • When scope data changed, chart will be open.

Example:

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

myModule.controller('myController', function($scope, chartService) {
  $scope.chartdata = chartService.getDataWithService();
});

myModule.factory('chartService', function($http) {
  return {
    getDataWithService: function() {
      var url = "yourServiceURL";
      return $http.get(url);
    },
    getData: function() {
      return {
        type: 'line',
        series: [{
          values: [54, 23, 34, 23, 43]
        }, {
          values: [10, 15, 16, 20, 40]
        }]
      };
    }
  };
});

html:

 <zingchart id="chart-1" zc-values="chartdata" zc-json="myJson" zc-width="100%" zc-height="568px"></zingchart>
like image 3
hurricane Avatar answered Oct 17 '22 13:10

hurricane