Angular Chartjs How to make it reactive to data change? - javascript

I'm trying to write an app that will show some data from API and during the work I will be able to change time and date range that I would like to show on the chart.
Right now I am fighting with basic data change.
I have a simple chart code:
HTML:
<button type="button" class="btn btn-success" ng-click="ReloadChart();">Reload</button>
<div class="col-lg-12 col-sm-12" id="line-chart" ng-controller="LineCtrl">
<div class="panel panel-default">
<div class="panel-heading">Line Chart</div>
<div class="panel-body">
<canvas id="line" class="chart chart-line" chart-data="data" chart-labels="labels"
chart-legend="true"
chart-click="onClick" chart-hover="onHover" chart-series="series"
chart-options="{pointHitDetectionRadius: 1}"></canvas>
</div>
</div>
</div>
And JS:
$scope.labels = ["January", "February", "March", "April", "May"];
$scope.series = ["Temperatura"];
$scope.data = [[22, 33, 44, 55, 22]];
$scope.ReloadChart = function () {
console.log("Reloading chart");
$scope.labels =
["January", "February", "March", "April", "May", "June", "July"];
$scope.series = ["Temperatura"];
$scope.data = [[65, 59, 80, 81, 56, 55, 40]];
}
Of course its just a part of longer code.
What I would like to this part do, is to reload the Chart with new data from ReloadChart() function. But the problem is that nothing is changing. In the console I have "Reloading Chart" but the chart is still the same.
What am I doing wrong?

Move ng-controller="LineCtrl" so it's outside of the button element, otherwise you will have the wrong scope involved.

Related

angular-chart does not show the series at the top like documentation

angular-chart.js has a bar-chart example is here. From here I used that js and markup code with some modification like this.
html
<body ng-app="app">
<div class="row">
<div class="col-md-6">
<div ng-controller="BarCtrl">
<canvas id="bar" class="chart chart-bar"
chart-data="data" chart-labels="labels" chart-series="series" chart-options="options" >
</canvas>
</div>
</div>
</div>
js
var app = angular.module('app', ['chart.js']);
app.controller('BarCtrl', ['$scope', function($scope){
$scope.labels = ['PDM', 'R&D', 'SN', 'MB'];
$scope.series = ['Late', 'NoLate'];
$scope.data = [
[10,2,1,2],
[5,3,2,4]
];
}]);
for more check https://plnkr.co/edit/jIqY72Lg4YvkMNbmawyC?p=preview
But the problem is my code doesn't show like with the marked option.
What I do wrong or any update I have to do?
You need to configure under options,
$scope.options = {
legend: {
display: true,
position: 'top'
}
};
DEMO

Charts.js & Bootstrap Accordion

I have been trying to understand why Charts.js wouldn't draw a chart if it's inside a Bootstrap Accordion.
After many attempts I managed to understand why it's not drawing the chart! it's because the panel is basically hiding the canvas so Charts.js doesn't draw it.
Can anyone help me come up with a solution to this?
I've also tried to draw the chart only when the Bootstrap event shown.bs.collapse is active, doesn't work.
Here's a jsfiddle I've created to illustrate the problem:
If you want to reproduce the problem simply add in to the class in line <div id="collapseOne" class="panel-collapse collapse" role="tabpanel" aria-labelledby="headingOne">
I got it to work with the following code:
<div class="panel-group" id="accordion" role="tablist" aria-multiselectable="true">
<div class="panel panel-default">
<div class="panel-heading" role="tab" id="headingOne">
<h4 class="panel-title">
<a role="button" data-toggle="collapse" data-parent="#accordion" href="#collapseOne" aria-expanded="true" aria-controls="collapseOne">
Collapsible Group Item #1
</a>
</h4>
</div>
<div id="collapseOne" class="panel-collapse collapse" role="tabpanel" aria-labelledby="headingOne">
<div class="panel-body">
<canvas id="q_chart" width="400" height="400"></canvas>
</div>
</div>
</div>
</div>
and javascript
var ctx = document.getElementById("q_chart").getContext("2d");
var data = {
labels: ["January", "February", "March", "April", "May", "June", "July"],
datasets: [{
label: "My First dataset",
fillColor: "rgba(220,220,220,0.2)",
strokeColor: "rgba(220,220,220,1)",
pointColor: "rgba(220,220,220,1)",
pointStrokeColor: "#fff",
pointHighlightFill: "#fff",
pointHighlightStroke: "rgba(220,220,220,1)",
data: [65, 59, 80, 81, 56, 55, 40]
}, {
label: "My Second dataset",
fillColor: "rgba(151,187,205,0.2)",
strokeColor: "rgba(151,187,205,1)",
pointColor: "rgba(151,187,205,1)",
pointStrokeColor: "#fff",
pointHighlightFill: "#fff",
pointHighlightStroke: "rgba(151,187,205,1)",
data: [28, 48, 40, 19, 86, 27, 90]
}]
};
var MyNewChart=null;
$('#collapseOne').on('shown.bs.collapse', function () {
setTimeout(function() {
if(MyNewChart == null)
MyNewChart = new Chart(ctx).Bar(data);
},200);
});
I did some testing and found that you can call MyNewChart.update() instead of recreating the chart on a timeout as the verified answer does. The first transition is a bit rough (maybe because a transition is happening as it's created) but after that the transitions are smooth.
Example JSFiddle: https://jsfiddle.net/akh9cnx5/
<div class="container">
<button type="button" class="col-12 btn btn-light mb-2" data-toggle="collapse" data-target="#viewgraph" aria-expanded="false" aria-controls="viewgraph">View Graph</button>
<div id="viewgraph" class="collapse mb-2">
<div class="card card-body">
<div class="d-flex justify-content-center">
<div class="col-12 col-sm-8">
<canvas id="graph"></canvas>
</div>
</div>
</div>
</div>
</div>
and javascript
var ctx = document.getElementById('graph').getContext('2d');
var data = {
labels: ["January", "February", "March", "April", "May", "June", "July"],
datasets: [{
label: "My First dataset",
fillColor: "rgba(220,220,220,0.2)",
strokeColor: "rgba(220,220,220,1)",
pointColor: "rgba(220,220,220,1)",
pointStrokeColor: "#fff",
pointHighlightFill: "#fff",
pointHighlightStroke: "rgba(220,220,220,1)",
data: [65, 59, 80, 81, 56, 55, 40]
}, {
label: "My Second dataset",
fillColor: "rgba(151,187,205,0.2)",
strokeColor: "rgba(151,187,205,1)",
pointColor: "rgba(151,187,205,1)",
pointStrokeColor: "#fff",
pointHighlightFill: "#fff",
pointHighlightStroke: "rgba(151,187,205,1)",
data: [28, 48, 40, 19, 86, 27, 90]
}]
};
var myNewChart = new Chart(ctx, {
type: 'bar',
data: data
});
$("#viewgraph").on('shown.bs.collapse', function () {
myNewChart.update();
});
For anyone coming to this later, I had the same issue but preferred not to rely on a timer delay as offered in the accepted answer. The following is what worked for me using Bootstrap 3.3.7 with the shown event:
shown.bs.collapse
$('#accordion').on('shown.bs.collapse', function (e) {
switch (e.target.id)
{
case "panel1": ShowChart1(); break;
case "panel2": ShowChart2(); break;
case "panel3": ShowChart3(); break;
case "panel4": ShowChart4(); break;
default: ShowDefault();
}
})
Hopes this helps
btw - this is the above code working: greatdata.com/stats/newyork_ny

chart.js pie chart issue with display: none

I have a problem with the pie chart when the container has a display property none in small devices and I have the following error :
Uncaught IndexSizeError: Failed to execute 'arc' on 'CanvasRenderingContext2D': The radius provided (-0.5) is negative.
my HTML code is
<div class="container-fluid charts hidden-xs">
<div class="row">
<div class="col-md-6 col-xs-12">
<div class="panel panel-default">
<div class="panel-heading">Annual sales</div>
<div class="panel-body">
<canvas class="annualChart" width="400" height="400"></canvas>
</div>
</div>
</div>
<div class="col-md-6 col-xs-12">
<div class="panel panel-default">
<div class="panel-heading">Visitors per shop</div>
<div class="panel-body">
<canvas class="visitorsChart" width="400" height="400"></canvas>
<div id="legend"></div>
</div>
</div>
</div>
<div class="col-md-6 col-xs-12">
<div class="panel panel-default">
<div class="panel-heading">Fans</div>
<div class="panel-body">
<canvas class="annualfanschart" width="400" height="400" ></canvas>
</div>
</div>
</div>
<div class="col-md-6 col-xs-12">
<div class="panel panel-default">
<div class="panel-heading">General sales</div>
<div class="panel-body">
<canvas class="generalSalesChart" width="400" height="400"></canvas>
</div>
</div>
</div>
</div>
</div>
and my JS code for the pie chart div is (the others are line and bar charts)
var data = [
{
value: 300,
color:"#F7464A",
highlight: "#FF5A5E",
label: "Men"
},
{
value: 50,
color: "#46BFBD",
highlight: "#5AD3D1",
label: "Women"
},
{
value: 100,
color: "#FDB45C",
highlight: "#FFC870",
label: "Children",
}
];
var options = {
animationSteps : 100,
animationEasing : "easeOutBounce",
animateRotate : true,
animateScale : true
}
var ctx = $(".visitorsChart").get(0).getContext("2d");
var myPieChart = new Chart(ctx).Pie(data,{
legendTemplate : "<ul class=\"<%=name.toLowerCase()%>-legend\"><% for (var i=0; i<segments.length; i++){%><li><span style=\"background-color: <%=segments[i].fillColor%>\"></span><%if(segments[i].label){%> <%=segments[i].label%><%}%></li><%}%></ul>"
});
var legend = myPieChart.generateLegend();
$("#legend").html(legend);
I face this problem only with the pie type, the other types doesn't show errors
There's currently a bug in chart.js: https://github.com/nnnick/Chart.js/issues/592
Try to skip chart rendering if the element is not visible
if ($(".visitorsChart").is(":visible")) {
var ctx = $(".visitorsChart").get(0).getContext("2d");
var myPieChart = new Chart(ctx).Pie(data,{});
}

Chart.js not showing in my view

I have an app running with angular.js and one of my view should load an chart. I'm using chart.js for it, but for some reason it's not working and no error is shown on my console.
Here is my function that creates the chart:
$scope.writeBatteryChart = function(){
console.log("Function was called");
var data = {
labels: ["10:30am", "11:00am", "11:30am", "12:00pm", "12:30pm", "01:00pm", "01:30pm"],
datasets: [
{
label: "Battery",
fillColor: "rgba(220,220,220,0.2)",
strokeColor: "rgba(220,220,220,1)",
pointColor: "rgba(220,220,220,1)",
pointStrokeColor: "#fff",
pointHighlightFill: "#fff",
pointHighlightStroke: "rgba(220,220,220,1)",
data: [65, 59, 80, 81, 56, 55, 40]
}
]
};
var options = {
responsive: true,
bezierCurve : false
}
var ctx = document.getElementById("myChart").getContext("2d");
var myLineChart = new Chart(ctx).Line(data, options);
}
Here's the HTML where the chart should appear:
<div class="row">
<div class="col-md-8 col-sm-8 col-xs-8" style="padding-left: 0px;">
<div class="panel panel-info">
<div class="panel-heading">
<h3 class="panel-title">Battery <i class="fi-battery-half"></i></h3>
</div>
<div class="panel-body">
<canvas id="myChart" height="300"></canvas>
</div>
</div>
</div>
<div class="col-md-4 col-sm-4 col-xs-4" style="padding-left: 0px; padding-right: 0px;">
</div>
</div>
and I'm also loading the latest version of the Chart.js:
<!--Chart plugin -->
<script src="bower_components/Chart.js/Chart.js" language="javascript"></script>
One thing that I noticed is that the canvas is being rendered with 0 dimensions:
Does someone can see where I'm doing something wrong?
The problem: I was calling the function before the canvas be loaded on the view, so I used a setTimeout() to call the writeBatteryChart() with a delay in order to wait the canvas be rendered.
You have to add your rendered things inside of canvas. Hope it will help Link

How to display angular js bar graph in modal popups

Hi I am trying to display angular js bar chart in modal popup (jquery modal), But its not working. I have tried with the below code.
<div class="modal fade bs-example-modal-lg" tabindex="-1" role="dialog" aria-labelledby="myLargeModalLabel" aria-hidden="true">
<div class="modal-dialog modal-lg">
<div class="modal-content widg_larg">
<div class="title">Modal Title
<span class="pull-right cursor_pointer">
<i class="fa fa-times" data-dismiss="modal" aria-label="Close"></i>
</span>
<div ng-controller="testConrtoller">
<canvas class="chart chart-bar" data="data"
labels="labels" width="400" height="400"></canvas>
</div>
</div>
</div>
</div>
</div>
and js code is
app.controller("testController", function ($scope, $http) {
$scope.labels = ["January", "February", "March", "April", "May", "June", "July"];
$scope.series = ['Series A', 'Series B'];
$scope.data = [
[65, 59, 80, 81, 56, 55, 40],
[28, 48, 40, 19, 86, 27, 90]
];
$scope.onClick = function (points, evt) {
console.log(points, evt);
};
});
But its not working is there any other way to work with it.

Categories