Friday, April 22, 2016

Why will a change on $scope.data on a onChange callback not re-plot chart.js?

Leave a Comment

I have an application that is written around the MEAN web stack. I have created an API that depending upon the URL a JSON data set is returned for given weights. This is interconnected with my Mongo database. There are two returned JSON types, one for all weights and another for weights that fall between two dates. Not only am I displaying all of these weights in the first instance on one page(home/index), but I am also displaying by a filtered set(by date) on an independent page. This independent page utilizes both angular-chart.js and ngDaterangepicker. These are both Angular directives that are injected into my code.

When a date range is selected a ng-change function runs (change()) which grabs a new set of filtered data(by date). This data is then added back into $scope.data the property, which when changed, should theoretically cause the chart to re-plot. Unfortunately, my application is not watching for new changes to this property inside of a on-change function.

If a timeout is set outside of this function the graph will re-plot. So I am wondering if there is a better way or a different way to solve this problem.

According to the documentation from angular-chart if there is any change to the value of $scope.data the chart will re-plot the new values, however anything inside of an on change event listener/function will cause any new values set to $scope.data to not be bound and cause the graph not to replot the new values. Why is the ng-change directive so special? Below is my HTML and JavaScript.

=== HTML View ===

<div class="container-fluid"> <h1 class="text-center">Graphs</h1>     <div class="container"> <div class="col-sm-12" ng-controller="weights">     <input type="text" ng-change="change()" ng-model="model"/>         <input type="daterange" ng-change="change({{myDateRange | json}})" ng-model="myDateRange" />         {{myDateRange | json}}         {{data}} </div>     <div class="col-sm-12">     <div class="col-sm-2"></div>     <div class="col-sm-8 center-block">         <div ng-controller="weights">     <canvas id="line" class="chart chart-line" chart-data="data"   chart-labels="labels" chart-legend="true" chart-series="series"   chart-click="onClick"> </canvas>  </div> </div> <div class="col-sm-2"></div> </div>     </div> </div> 

=== Angular Controller ===

angular.module('app').controller('weights', ['$scope', 'weightsFactory','$filter','$http', '$timeout', function($scope, weightsFactory, $filter, $http, $timeout){     //need to get weights from /weights     //$scope.labels = [1, 2, 3, 4];      $scope.series = ['Weights Over Time'];     $http.get('/weights').success(function(data){ //all data     var dates = [];      var weights = [];      $scope.weights = data;       angular.forEach(data, function(value, key){         dates.push($filter('date')(value.date, 'MMM dd, yyyy - hh:m:ss a'));         weights.push(value.weight);      });         $scope.labels = dates;      $scope.data = [ weights ];     });  $scope.change = function(data){      //2016-04-08T04:00:00.000Z/2016-04-09T03:59:59.999Z      var startTime = '2016-04-08T04:00:00.000Z';       var endTime = '2016-04-09T03:59:59.999Z';      $http.get('/weight/range/'+startTime+'/'+endTime).success(function(response){         $timeout(function() {             $scope.data = [['100', '200', '300']]; //this data is being set but is not causing a change on chart.js         }, 10);      });         } 

3 Answers

Answers 1

I wasted 50+ bounty on this question, however it is safe to assume that you can have the same controller in an application, however if you nest two controllers together then yes the application will work, however you will have essentially two different $scope variables in memory. I am not going to remove my error only to prove that if all else fails, look for identical controllers. Be careful with your HTML.

Answers 2

As far as i can see your $scope.change function resides outside of the weights controller scope, hence unreachable by ng-change

Answers 3

i would imaging your controller is being loaded twice.

<div ng-controller="weights"> <div class="col-sm-12" ng-controller="weights"> 

if you were to remove them both and add the controller to the container-fluid div, you should be able to share the state of the controller with the ng-change directive.

<div class="container-fluid" ng-controller="weights">     <h1 class="text-center">Graphs</h1>     <div class="container">         <div class="col-sm-12">             <input type="daterange" ng-change="change({{myDateRange | json}})" ng-model="myDateRange" />                  {{myDateRange | json}} {{data}}         </div>     </div>     <div class="col-sm-12">         <div class="col-sm-2"></div>         <div class="col-sm-8 center-block"> ...             <div>                 <canvas></canvas>             </div>         </div>         <div class="col-sm-2"></div>     </div> </div> 

angular-charts ng-change example

If You Enjoyed This, Take 5 Seconds To Share It

0 comments:

Post a Comment