GraFiddle / angular-chart

AngularJS directive for adjustable dynamically updating c3 charts
http://grafiddle.github.io/angular-chart/
MIT License
127 stars 40 forks source link

Update Dimensions Dynamically #95

Closed bontorhumala closed 9 years ago

bontorhumala commented 9 years ago

Hello, how can I update the Dimensions dynamically to change how date is presented on x-axis? I have a dropdown button where user can pick specific time range to display data and would like to $scope.options to pick the changes automatically. Using $scope. doesnt seem to work:

$scope.$watch('range', function() {
console.log("range changed");
$scope.options.dimensions = {
  sales: {
    type: 'bar'
  },
  income: {
    axis: 'y2'
  },
  date: {
    dataType: 'datetime',
    dataFormat: '%Y-%m-%d_%H:%M:%S',
    displayFormat: function (x) {
      return selectFormat(x);
    },
    axis: 'x',
    label: true,
  }
}
});

var selectFormat = function (x) { 
if ( $scope.range.power == 'Today' ) {
  var hours = x.getHours();
  var ampm = hours > 12 ? 'pm' : 'am';
  hours = hours % 12;
  hours = hours ? hours : 12; // the hour '0' should be '12'
  var strTime = hours + ' ' + ampm;

  return strTime;
}
else if (( $scope.range.power == 'This week' ) || ( $scope.range.power == 'Last week' )) {
  var days = $scope.days[ x.getDay() ];
  var hours = x.getHours();
  var ampm = hours > 12 ? 'pm' : 'am';
  hours = hours % 12;
  hours = hours ? hours : 12; // the hour '0' should be '12'
  var strTime = days + ' ,' + hours + ' ' + ampm;

  return strTime;
}
else if (( $scope.range.power == 'This month' ) || ( $scope.range.power == 'Last month' )){
  var date = $scope.days[ x.getDay() ];
  var month = $scope.months[ x.getMonth() ];            
  var strTime = month + ' ' + date;

  return strTime;
}
else if ( $scope.range.power == 'This year' ) {
  var hours = x.getHours();
  var ampm = hours > 12 ? 'pm' : 'am';
  hours = hours % 12;
  hours = hours ? hours : 12; // the hour '0' should be '12'
  var date = $scope.days[ x.getDay() ];
  var month = $scope.months[ x.getMonth() ];            
  var strTime = month + ' ' + date + ', ' + hours + ' ' + ampm;

  return strTime;
}          
}

$scope.options = {
data: [
  {
    sales: 130,
    income: 250,
    date: '2015-04-04_12:13:55'
  },
  {
    sales: 135,
    income: 212,
    date: '2015-04-04_13:13:55'
  },
  {
    sales: 141,
    income: 229,
    date: '2015-04-04_14:13:55'
  }
],
dimensions: {
  sales: {
    type: 'bar'
  },
  income: {
    axis: 'y2'
  },
  date: {
    dataType: 'datetime',
    dataFormat: '%Y-%m-%d_%H:%M:%S',
    displayFormat: function (x) {
      return selectFormat(x);
    },
    axis: 'x',
    label: true,
  }
},
chart: {
  subchart: {
    show: true
  }
}

};
maxklenk commented 9 years ago

Hi @bontorhumala, your code nearly works, there are only small changes to do. You can find a working example here: http://plnkr.co/edit/zdvieM?p=preview

What to fix?

$scope.$watch('range', function() {}, true) If you want to watch for changes inside an object you have to do a deep watch, the normal watch only checks if a new value is assigned to $scope.range.

The chart only rerenders and applies the new displayFormat when something in the options change. The code you apply inside the watcher sets the same configuration as earlier, because you link the same selectFormat function again. There are multiple ways to solve this. An easy solution would be to simply update some value inside the options to trigger the watchers inside of angular-chart.

$scope.$watch('range', function() {
    console.log("range changed");
    $scope.options.chart.updated = (new Date()).getTime();
  }, true);

I hope this solves your problems.