Pie chart with Chart.js and mySQL - javascript

I'm trying to display a pie chart using the result of some queries. But nothing is showing. I don't know where the mistake is in my javascript:
$(document).ready(function(){
$.ajax({
url:"http://localhost/bigdata/data.php",
method:"GET",
success:function(data) {
console.log(data);
var male =[];
var female =[];
male.push("male: "+data[0].maleid);
female.push("female: "+data[1].femaleid);
var data1 = {
labels: [
"Male",
"Female"
],
datasets: [
{
data: [male,female],
backgroundColor: [
"#FF6384",
"#36A2EB"
],
hoverBackgroundColor: [
"#FF6384",
"#36A2EB"
]
}]
};
var ctx =$("#mycanvas");
var myPieChart = new Chart(ctx,{
type: 'doughnut',
data: data1,
options: {
animation:{
animateScale:true,
responsive: true,
maintainAspectRatio: true
}
}
});
},
error:function(data){
console.log(data);
}
});
});
<!-- end snippet--!>
Besides , my php code of query execution works also my html page .
<!-- begin snippet: js hide: false console: true babel: false -->
<!DOCTYPE html>
<html>
<head>
<meta charset ="utf-8"/>
<title>Chart</title>
<style type="text/css">
#chart-container{
width:640px;
height:auto;
}
</style>
</head>
<body>
<div id="chart-container">
<canvas id="mycanvas"></canvas>
</div>
<script src="Chart.js"></script>
<script src="jquery-3.2.1.js"></script>
<script src="app.js"></script>
</body>
</html>
<?php
header('Content-Type:application\json');
define('DB_HOST','127.0.0.1');
define('DB_USERNAME','root');
define('DB_PASSWORD','');
define('DB_NAME','gestionpersdb');
$mysqli=new mysqli(DB_HOST,DB_USERNAME,DB_PASSWORD,DB_NAME);
if(!$mysqli)
{
die("connection failed:".$myqli->error);
}
$male="SELECT * FROM gestiondb_users WHERE gender='male'";
$result_male=$mysqli->query($male);
$num_males=mysqli_num_rows($result_male);
$female="SELECT * FROM gestiondb_users WHERE gender='female'";
$result_female=$mysqli->query($female);
$num_females=mysqli_num_rows($result_female);
$data=array();
$data[0]=$num_males;
$data[1]=$num_females;
$result_male->close();
$result_female->close();
$mysqli->close();
print json_encode($data);
?>

In case you're still trying to get it to work, here is how I did it:
<script type="text/javascript">
$.ajax({
url:"getdata.php",
method:"GET",
success:function(data) {
console.log(data);
var malenum =[1];
var femalenum =[2];
var ctx = document.getElementById("myChart");
var myChart = new Chart(ctx, {
type: 'pie',
data: {
labels: ["Male","Female"],
datasets: [{
label: 'Genders',
data: [malenum,femalenum],
backgroundColor: [
'rgba(255, 99, 132, 0.2)',
'rgba(54, 162, 235, 0.2)'
],
borderColor: [
'rgba(255,99,132,1)',
'rgba(54, 162, 235, 1)'
],
borderWidth: 1
}]
},
});
},
error:function(data){
console.log(data);
}
});
</script>

Related

Chart.js - How to update data

I've created chart that shows temperature from past 20 minute. Data is obtained via GET request from my Thingspeak meteo station. How could I send new request every 10 seconds and update only data in chart.
I think chart.update() would work, but I have no idea how to implement it :/
Here is some code:
chartIt();
async function chartIt(){
const loadedData = await loadData();
var myChart = new Chart(document.getElementById("tempChart").getContext('2d'), {
type: 'line',
backgroundColor: 'rgba(255, 251, 230, 0.5)',
data: {
labels: loadedData.timeStamp,
datasets: [{
label: 'Temperature',
data: loadedData.chartData,
backgroundColor: [
'rgba(255, 0, 132, 0.2)'
],
borderColor: [
'rgba(255, 99, 132, 1)'
],
borderWidth: 1
}]
},
})
}
async function loadData() {
var chartData = [];
var timeStamp = [];
await $.getJSON('https://api.thingspeak.com/channels/214058/fields/1.json?minutes=20', function(data) {
$.each(data.feeds, function(){
var value = this.field1;
var raw_time = this.created_at;
if (value) {
value = (value / 1000) * 1000;
value = parseFloat(value.toFixed(2));
}
if (raw_time){
var timewZ = raw_time.split("T").slice(1);
}
chartData.push(value);
timeStamp.push(timewZ);
});
});
return {chartData, timeStamp};
}
.chartWrapper{
width: 500px;
height: 500px;
margin:auto;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="https://cdn.jsdelivr.net/npm/chart.js#2.8.0"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<link rel="stylesheet" href="style.css">
<title>Document</title>
</head>
<body>
<div class="chartWrapper">
<canvas id="tempChart"></canvas>
</div>
</body>
<script src="script.js"></script>
</html>
This is simplistic but would do the trick. If you wanted to enable/disable it, you'd want to hang onto your interval so you can kill it... This works though! :)
const updateFreqency = 10000;
chartIt(updateFreqency);
async function chartIt(interval){
const loadedData = await loadData();
var myChart = new Chart(document.getElementById("tempChart").getContext('2d'), {
type: 'line',
backgroundColor: 'rgba(255, 251, 230, 0.5)',
data: {
labels: loadedData.timeStamp,
datasets: [{
label: 'Temperature',
data: loadedData.chartData,
backgroundColor: [
'rgba(255, 0, 132, 0.2)'
],
borderColor: [
'rgba(255, 99, 132, 1)'
],
borderWidth: 1
}]
},
})
setInterval(async () => {
const data = await loadData();
myChart.data.datasets.forEach(d => d.data = data.chartData)
myChart.labels = data.timeStamp
myChart.update()
}, interval)
}
async function loadData() {
var chartData = [];
var timeStamp = [];
await $.getJSON('https://api.thingspeak.com/channels/214058/fields/1.json?minutes=20', function(data) {
$.each(data.feeds, function(){
var value = this.field1;
var raw_time = this.created_at;
if (value) {
value = (value / 1000) * 1000;
value = parseFloat(value.toFixed(2));
}
if (raw_time){
var timewZ = raw_time.split("T").slice(1);
}
chartData.push(value);
timeStamp.push(timewZ);
});
});
return {chartData, timeStamp};
}
.chartWrapper{
width: 500px;
height: 500px;
margin:auto;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="https://cdn.jsdelivr.net/npm/chart.js#2.8.0"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<link rel="stylesheet" href="style.css">
<title>Document</title>
</head>
<body>
<div class="chartWrapper">
<canvas id="tempChart"></canvas>
</div>
</body>
<script src="script.js"></script>
</html>
basically you need access to chart so if you move its context/scope to be outside of the function then you can access it from another function....
something like....
ommited some of the code as well this is the core bits..
//moved out
var myChart;
async function chartIt(){
const loadedData = await loadData();
myChart = new Chart(document.getElementById("tempChart").getContext('2d'), {
type: 'line',
backgroundColor: 'rgba(255, 251, 230, 0.5)',
data: {
labels: loadedData.timeStamp,
datasets: [{
label: 'Temperature',
data: loadedData.chartData,
backgroundColor: [
'rgba(255, 0, 132, 0.2)'
],
borderColor: [
'rgba(255, 99, 132, 1)'
],
borderWidth: 1
}]
},
})
}
function myTimer() {
var loadedData = await loadData();
//have access here as it was move out of the function which created it.
myChart.data.labels = loadedData.timeStamp;
myChart.data.datasets = loadedData.chartData;
myChart.update();
}
var myVar = setInterval(myTimer, 10000);

Cannot display two Chart.js on one HTML page

I am trying to display more Chart.js graphics on a single HTML page, but it does not work. I tried several approaches, but none of them had a positive result. I will attach my code:
#extends('layouts.app')
<!DOCTYPE html>
<html lang="zxx">
#section('content')
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<script src="https://code.jquery.com/jquery-3.3.1.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.3/Chart.js"></script>
<script src="https://cdn.jsdelivr.net/npm/patternomaly#1.3.2/dist/patternomaly.min.js"></script>
#php
$dates = '';
$rates = '';
$graph_data = \App\Helpers\NjHelper::bettingData();
foreach ($graph_data as $item){
$dates .= "'".$item->date."',";
$rates .= $item->bankers.",";
}
#endphp
#php
$datesValue = '';
$ratesValue = '';
$graph_data_value = \App\Helpers\NjHelper::bettingDataValueBets();
foreach ($graph_data_value as $item){
$datesValue .= "'".$item->date."',";
$ratesValue .= $item->value_bet.",";
}
#endphp
<script>
$(function () {
var ctx = document.getElementById('myChart').getContext('2d');
var myChart = new Chart(ctx, {
type: 'line',
data: {
labels: [{!! $dates !!}],
datasets: [{
label: 'Bankers Profit Per Day',
data: [{!! $rates !!}],
borderColor: [
'rgba(243, 156, 18, 1)',
'rgba(243, 156, 18, 1)',
'rgba(243, 156, 18, 1)'
],
borderWidth: 3
}]
},
options: {
scales: {
yAxes: [{
ticks: {
beginAtZero: true
}
}]
},
legend: {
labels: {
fontSize: 20
}
}
}
});
var ctx_2 = document.getElementById(chartValueBets).getContext('2d');
var chartValueBets = new Chart(ctx_2, {
type: 'line',
data: {
labels: [{!! $datesValue !!}],
datasets: [{
label: 'Value Bets Profit Per Day',
data: [{!! $ratesValue !!}],
borderColor: [
'rgba(243, 156, 18, 1)',
'rgba(243, 156, 18, 1)',
'rgba(243, 156, 18, 1)'
],
borderWidth: 3
}]
},
options: {
scales: {
yAxes: [{
ticks: {
beginAtZero: true
}
}]
},
legend: {
labels: {
fontSize: 20
}
}
}
});
});
</script>
</head>
<div class="col-lg-12 col-xl-4">
<canvas id="myChart" width="400" height="400"></canvas>
<canvas id="chartValueBets" width="400" height="400"></canvas>
</div>
#endsection
</html>
The data that I want to be displayed comes from some SQL queries, this is the reason why I have those two #php sections before the charts.
Only the first chart appears on my HTML page, the one with the name "myChart".
Does anyone know what I could do in order to make the second one appear as well?
On the following line:
var ctx_2 = document.getElementById(chartValueBets).getContext('2d');
You are missing quotation marks around "chartValueBets." If you add quotation marks, it should work properly.

Periodically refresh placeholder and canvas tag in Django template

I have a template that, among other things, displays a current market price through a placeholder, i.e., {{ market.current_price }}, and an accompanying price graph using ChartJS, rendered in the template in a canvas tag, <canvas id="myChart"></canvas>.
My question: since the market price changes as different users engage with the underlying market, is there a straightforward way to periodically (say, every 10 seconds) refresh the placeholder and chart in the template, to make sure each user is looking at the most recent price/graph?
I'm trying to avoid having to refresh the entire page, if at all possible.
If it makes any difference, the chart is rendered through Ajax, as follows:
{% block jquery %}
var endpoint = "{% url 'chart_data' market.id %}"
var defaultData = []
var labels = []
$.ajax({
method: "GET",
url: endpoint,
success: function(data){
defaultData = data.prices
price_array_length = defaultData.length + 1
labels = data.price_dates
var ctx = document.getElementById('myChart').getContext('2d');
var myChart = new Chart(ctx, {
type: 'line',
data: {
labels: labels,
datasets : [{
label: 'Market price',
data: defaultData,
backgroundColor: [
'rgba(54, 162, 235, 0.2)',
],
borderColor: [
'rgba(54, 162, 235, 1)',
],
borderWidth: 2
}]
},
options: {
scales: {
yAxes: [{
ticks: {
suggestedMin: 0,
suggestedMax: 1
}
}]
},
animation: {
duration: 500 // general animation time
},
hover: {
animationDuration: 500 // duration of animations when hovering an item
},
responsiveAnimationDuration: 500 // animation duration after a resize
}
})
}
})
{% endblock %}
Many thanks in advance for any advice!
Here's one solution: Building on #MichaelCacciano's suggestion, I wrapped the JQuery in a function (refresh_graph), and also dropped the Django placeholder in favour of a tag (currentPrice), both of which now update every second, as follows:
<script>
function refresh_graph() {
{% block jquery %}
var endpoint = "{% url 'chart_data' market.id %}"
var defaultData = []
var labels = []
$.ajax({
method: "GET",
url: endpoint,
success: function(data){
defaultData = data.prices
price_array_length = defaultData.length + 1
labels = data.price_dates
var current = defaultData[defaultData.length-1];
document.getElementById('currentPrice').innerHTML = current;
var ctx = document.getElementById('myChart').getContext('2d');
var myChart = new Chart(ctx, {
type: 'line',
data: {
labels: labels,
datasets : [{
label: 'Market price',
data: defaultData,
backgroundColor: [
'rgba(54, 162, 235, 0.2)',
],
borderColor: [
'rgba(54, 162, 235, 1)',
],
borderWidth: 2
}]
},
options: {
scales: {
yAxes: [{
ticks: {
suggestedMin: 0,
suggestedMax: 1
}
}]
},
animation: {
duration: 0 // general animation time
},
hover: {
animationDuration: 0 // duration of animations when hovering an item
},
responsiveAnimationDuration: 500 // animation duration after a resize
}
})
}
})
setTimeout(refresh_graph, 1000);
}
setTimeout(refresh_graph, 0);
{% endblock %}
</script>

chart.js : empty doughnut after getting data from database

Putting data from a database into an array in chart.js is not working and gives an empty doughnut:
i'm using angular / spring boot for back end
constructor(private statistiqueService:StatistiqueService) {
this.statistiqueService.getStateClient().subscribe(
resp=>{
for(var i=0;i<resp.length;i++){
this.dataStatus[i]=resp[i][1];
this.labelStatus[i]=resp[i][0];
}
}
);
}
statusClient(){
var ctx = document.getElementById("myChart");
var myChart = new Chart(ctx, {
type: 'doughnut',
data: {
datasets: [{
data: this.dataStatus,
backgroundColor: [
'rgba(255, 99, 132, 0.8)',
'rgba(54, 162, 235, 0.8)'
]
}],
labels:this.labelStatus
}
});
}
ngOnInit() {
console.log("Data");
console.log(this.dataStatus);
console.log("Label");
console.log(this.labelStatus);
this.statusClient();
}
My data after log is here

How to use JSON data in creating a chart with chartjs?

In my controller I have an Action method that will find all questions in a table called Questions, and the answers for each question.
This Action is of type ContentResult that will return a result serialized in Json format.
public ContentResult GetData()
{
var datalistQuestions = db.Questions.ToList();
List<PsychTestViewModel> questionlist = new List<PsychTestViewModel>();
List<PsychTestViewModel> questionanswerslist = new List<PsychTestViewModel>();
PsychTestViewModel ptvmodel = new PsychTestViewModel();
foreach (var question in datalistQuestions)
{
PsychTestViewModel ptvm = new PsychTestViewModel();
ptvm.QuestionID = question.QuestionID;
ptvm.Question = question.Question;
questionlist.Add(ptvm);
ViewBag.questionlist = questionlist;
var agree = //query
var somewhatAgree = //query
var disagree = //query
int Agree = agree.Count();
int SomewhatAgree = somewhatAgree.Count();
int Disagree = disagree.Count();
ptvmodel.countAgree = Agree;
ptvmodel.countSomewhatAgree = SomewhatAgree;
ptvmodel.countDisagree = Disagree;
questionanswerslist.Add(ptvmodel);
ViewBag.questionanswerslist = questionanswerslist;
}
return Content(JsonConvert.SerializeObject(ptvmodel), "application/json");
}
Now, my problem is the pie chart is not being created and I don't quite know how to push the values to my data structure?
What should I be doing instead?
Here is my script:
#section Scripts {
<script type="text/javascript">
var PieChartData = {
labels: [],
datasets: [
{
label: "Agree",
backgroundColor:"#f990a7",
borderWidth: 2,
data: []
},
{
label: "Somewhat Agree",
backgroundColor: "#aad2ed",
borderWidth: 2,
data: []
},
{
label: "Disgree",
backgroundColor: "#9966FF",
borderWidth: 2,
data: []
},
]
};
$.getJSON("/PsychTest/GetData/", function (data) {
for (var i = 0; i <= data.length - 1; i++) {
PieChartData.datasets[0].data.push(data[i].countAgree);
PieChartData.datasets[1].data.push(data[i].countSomewhatAgree);
PieChartData.datasets[2].data.push(data[i].countDisagree);
}
var ctx = document.getElementById("pie-chart").getContext("2d");
var myLineChart = new Chart(ctx,
{
type: 'pie',
data: PieChartData,
options:
{
responsive: true,
maintainaspectratio: true,
legend:
{
position : 'right'
}
}
});
});
</script>
You need two arrays for creating your chart. One of them indicates titles and another one shows the number of each titles. You have titles in the client side, so you only need the number of each options and it could be fetched from a simple server method like:
[HttpGet]
public JsonResult Chart()
{
var data = new int[] { 4, 2, 5 }; // fill it up whatever you want, but the number of items should be equal with your options
return JsonConvert.SerializeObject(data)
}
The client side code is here:
var aLabels = ["Agree","Somewhat Agree","Disagree"];
var aDatasets1 = [4,2,5]; //fetch these from the server
var dataT = {
labels: aLabels,
datasets: [{
label: "Test Data",
data: aDatasets1,
fill: false,
backgroundColor: ["rgba(54, 162, 235, 0.2)", "rgba(255, 99, 132, 0.2)", "rgba(255, 159, 64, 0.2)", "rgba(255, 205, 86, 0.2)", "rgba(75, 192, 192, 0.2)", "rgba(153, 102, 255, 0.2)", "rgba(201, 203, 207, 0.2)"],
borderColor: ["rgb(54, 162, 235)", "rgb(255, 99, 132)", "rgb(255, 159, 64)", "rgb(255, 205, 86)", "rgb(75, 192, 192)", "rgb(153, 102, 255)", "rgb(201, 203, 207)"],
borderWidth: 1
}]
};
var opt = {
responsive: true,
title: { display: true, text: 'TEST CHART' },
legend: { position: 'bottom' },
//scales: {
// xAxes: [{ gridLines: { display: false }, display: true, scaleLabel: { display: false, labelString: '' } }],
// yAxes: [{ gridLines: { display: false }, display: true, scaleLabel: { display: false, labelString: '' }, ticks: { stepSize: 50, beginAtZero: true } }]
//}
};
var ctx = document.getElementById("myChart").getContext("2d");
var myNewChart = new Chart(ctx, {
type: 'pie',
data: dataT,
options: opt
});
<script src="https://github.com/chartjs/Chart.js/releases/download/v2.7.1/Chart.min.js"></script>
<div Style="font-family: Corbel; font-size: small ;text-align:center " class="row">
<div style="width:100%;height:100%">
<canvas id="myChart" style="padding: 0;margin: auto;display: block; "> </canvas>
</div>
</div>
If you are still looking to use json for chart.js charts.
Here is a solution which fetch a json file and render it on chart.js chart.
fetch('https://s3-us-west-2.amazonaws.com/s.cdpn.io/827672/CSVtoJSON.json')
.then(function(response) {
return response.json();
})
.then(function(ids) {
new Chart(document.getElementById("bar-chart"), {
type: 'bar',
data: {
labels: ids.map(function(id) {
return id.Label;
}),
datasets: [
{
label: "value2",
backgroundColor: ["#3e95cd", "#8e5ea2","#3cba9f","#e8c3b9","#c45850"],
data: ids.map(function(id) {
return id.Value2;
}),
},
{
label: "value",
//backgroundColor: ["#3e95cd", "#8e5ea2","#3cba9f","#e8c3b9","#c45850"],
data: ids.map(function(id) {
return id.Value;
}),
},
]
},
options: {
legend: { display: false },
title: {
display: true,
text: 'Sample Json Data Chart'
}
}
});
});
see running code on jsfiddle here

Categories