I've been trying to add chart.js to my Django Project, which worked pretty fine so far. I made a doughnut-chart with two slices. Now i want to have each of those slices to have seperate actions on click, like for example redirecting to new side.
These are my chart settings:
var config = {
type: 'doughnut',
data: {
datasets: [{
data: {{ data|safe }}, // Error because django and js are being mixed
backgroundColor: [
'#ff0000', '#008000'
],
label: 'Population'
}],
labels: {{ labels|safe }}
},
options: {
responsive: true
}
};
And this is the rendering and my function to make the actions on click:
window.onload = function() {
var ctx = document.getElementById('pie-chart').getContext('2d');
var myPieChart = new Chart(ctx, config);
$('#myChart').on('click', function(event) {
var activePoints = myPieChart.getElementsAtEvent(event)
if(activePoints[0]){
console.log("Helo 1")
}
else {
console.log("helo 2")
}
})
};
I saw my solution on other pages, but it doesn't work at all. Am I missing something? If yes could you please help?
getElementAtEvent has been replaced with chart.getElementsAtEventForMode in Chart.js v3 (see 3.x Migration Guide).
Please take a look at below runnable code and see how it works now:
const pieChart = new Chart("myChart", {
type: 'pie',
data: {
labels: ["Red", "Blue", "Yellow"],
datasets: [{
data: [8, 5, 6],
backgroundColor: ["#FF6384", "#36A2EB", "#FFCE56"],
}]
},
options: {
onClick: evt => {
var elements = pieChart.getElementsAtEventForMode(evt, 'index', { intersect: true }, false);
var index = elements[0].index;
console.log(pieChart.data.labels[index] + ': ' + pieChart.data.datasets[0].data[index]);
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.9.1/chart.min.js"></script>
<canvas id="myChart"></canvas>
fairly new to JS and I have a strange issue with chart JS bar chart.
<script>
$(document).ready(function() {
var bar = document.getElementById("chart-bar-11").getContext('2d');
var data1 = {
labels: ["Yesterday"],
datasets: [{
label: "Win",
data: [{{ gam }}],
borderColor: '#4099ff',
backgroundColor: '#4099ff',
hoverborderColor:'#4099ff',
hoverBackgroundColor: '#4099ff',
}, {
label: "Lose",
data: [{{ results }}],
borderColor: '#0e9e4a',
backgroundColor: '#0e9e4a',
hoverborderColor:'#0e9e4a',
hoverBackgroundColor: '#0e9e4a',
}]
};
var myBarChart = new Chart(bar, {
type: 'bar',
data: data1,
options: {
barValueSpacing: 20
}
});
});
</script>
I have a simplke bar chart, but here is a screen shot of current behavior, super confused how this chart shows it has both datasets but will only display the larger dataset?
Ended up finding the options needed in another Chart JS post, this is what I was missing.
var myBarChart = new Chart(bar, {
type: 'bar',
data: data1,
options: {
scales: {
yAxes: [{
ticks: {
beginAtZero: true
}
}]
}
}
});
It appears he "beginAtZero" is what was missing. This now works as expected.
I have sqlite database with single table. I am trying to read data with Python and pandas and return the data as json file in a function. Then the goal is to use Javascript to fetch the json data and use it for chart.js.
Here is my Python Code that should read the data form the database:
#cherrypy.expose
def chart_data(self):
cnx = sqlite3.connect('Production.db', check_same_thread=False)
daily_df = pd.read_sql_query("SELECT * FROM data_object", cnx)
return daily_df.to_json()
Then here is the part of the JavaScript code that I am trying to use to fetch data from that python call:
function get_chart_data() {
fetch('/chart_data').then( x => {
return x.json();
}).then( x => {
console.log(x);
});
}
In this instance i am trying to print the data in console.log just to see if i am getting data from Python. However I need this data to be fed into chart.js
var data = {
labels: [],
datasets: [{
label: "Dataset",
backgroundColor: "rgba(255,99,132,0.2)",
borderColor: "rgba(255,99,132,1)",
borderWidth: 2,
hoverBackgroundColor: "rgba(255,99,132,0.4)",
hoverBorderColor: "rgba(255,99,132,1)",
data: [],
}]
};
var options = {
maintainAspectRatio: false,
scales: {
yAxes: [{
stacked: true,
gridLines: {
display: true,
color: "rgba(255,99,132,0.2)"
}
}],
xAxes: [{
gridLines: {
display: false
}
}]
}
};
Chart.Bar('chart', {
options: options,
data: data
});
And finally, the sqilite table has these columns:timestamp,capacity,max_capacity, true_count.
There is only 24 rows of data, one for each hour of the day.
And here is where I am stuck. I am not sure how to properly pull this data into the chart. The goal is to plot true count over the 24h period.
With the code I have so far I know i am very close but i am missing something to make this work.
Am I pulling the data properly with javascript from python?
And how do i then push that json data in javascript into label variable and data variable in chart.js?
I have made some progress. I am now able to get data to javascript console log while using your ajax example.
/* chart.js chart examples */
$(document).ready(function(){
var _data;
var _labels;
$.ajax({
url: "chart_data",
type: "get",
success: function(response) {
full_data = JSON.parse(response);
_data = full_data['true_count'];
_labels = full_data['timestamp'];
},
});
// chart colors
var colors = ['#007bff','#28a745','#333333','#c3e6cb','#dc3545','#6c757d'];
/* large line chart */
var chLine = document.getElementById("chLine");
var chartData = {
labels:_labels,
datasets: [
{
data:_data,
backgroundColor: [
'rgba(42, 157, 244, 0.1)'
],
borderColor: [
'rgba(42, 157, 244, 1)',
'rgba(33, 145, 81, 0.2)',
],
borderWidth: 1
}]
};
if (chLine) {
new Chart(chLine, {
type: 'line',
data: chartData,
options: {
scales: {
yAxes: [{
ticks: {
beginAtZero: false
}
}]
},
legend: {
display: false
}
}
});
}
;
});
So if i do console.log(full_data) i get my data from python in json format as i wanted. However, i am getting error that says: full_data is not defined at the line where I am saying that labels: full_data['timestamp']
It seems that my full data is not accessable from the chart block. I am sure i am misplacing few brackets to make this work but I am unable to figure out where.
Any ideas?
My json file looks like this:
[{"timestamp":"00:00:00.000000","true_count":0},{"timestamp":"01:00:00.000000","true_count":0},{"timestamp":"02:00:00.000000","true_count":0},{"timestamp":"03:00:00.000000","true_count":0},{"timestamp":"04:00:00.000000","true_count":0},{"timestamp":"05:00:00.000000","true_count":0},{"timestamp":"06:00:00.000000","true_count":2},{"timestamp":"07:00:00.000000","true_count":5},{"timestamp":"08:00:00.000000","true_count":7},{"timestamp":"09:00:00.000000","true_count":8},{"timestamp":"10:00:00.000000","true_count":12},{"timestamp":"11:00:00.000000","true_count":15},{"timestamp":"12:00:00.000000","true_count":20},{"timestamp":"13:00:00.000000","true_count":17},{"timestamp":"14:00:00.000000","true_count":14},{"timestamp":"15:00:00.000000","true_count":13},{"timestamp":"16:00:00.000000","true_count":11},{"timestamp":"17:00:00.000000","true_count":19},{"timestamp":"18:00:00.000000","true_count":22},{"timestamp":"19:00:00.000000","true_count":16},{"timestamp":"20:00:00.000000","true_count":14},{"timestamp":"21:00:00.000000","true_count":10},{"timestamp":"22:00:00.000000","true_count":7},{"timestamp":"23:00:00.000000","true_count":4}]
I have been trying to parse this so timestamp goes to _labels and true_count goes to _data but no luck.
Here is what i have:
$(document).ready(function(){
var _data =[];
var _labels = [];
$.ajax({
url: "chart_data",
type: "get",
success: function(response) {
full_data = JSON.parse(response);
full_data.forEach(function(key,index){
_data = key.true_count;
_labels= key.timestamp;
});
//_data = [full_data['true_count']];
//_labels = [full_data['timestamp']];
},
});
Any suggestion what am I doing wrong now?
I am sharing my example which I used using Google charts .I am fetching live data from OPC Server using ajax and updated my real-time graph. It won't be a big difference if you use database instead of opc server. I hope you can relate it with your example.
Html
<div class="row" id="grap">
<div class="col-lg-12">
<div class="row">
<div class="col-12">
<div class="card">
<div class="chart-wrapper">
<div id="graph"></div>
</div>
</div>
</div>
</div>
</div>
</div>
This is django file from where I am passing data to gettemp() function via ajax call in json format. In your case it is database and there wont be issue.
Views.py
def plcdata(request):
url="opc.tcp://127.0.0.1:9000"
client=Client(url)
client.connect()
print("Client Connected")
data={}
dt=[]
while True:
pres=client.get_node("ns=2;i=2")
Pressure=pres.get_value()
adp=client.get_node("ns=2;i=3")
ap=adp.get_value()
rh=client.get_node("ns=2;i=4")
r=rh.get_value()
sp=client.get_node("ns=2;i=5")
s=sp.get_value()
nitro=client.get_node("ns=2;i=6")
n=nitro.get_value()
o2n=client.get_node("ns=2;i=7")
o=o2n.get_value()
hgl=client.get_node("ns=2;i=8")
h=hgl.get_value()
stempress=client.get_node("ns=2;i=9")
sps=stempress.get_value()
cond=client.get_node("ns=2;i=10")
co=cond.get_value()
dmwp=client.get_node("ns=2;i=11")
dmp=dmwp.get_value()
dmwf=client.get_node("ns=2;i=12")
dmf=dmwf.get_value()
chwp=client.get_node("ns=2;i=13")
chp=chwp.get_value()
chwt=client.get_node("ns=2;i=14")
cht=chwt.get_value()
icp=client.get_node("ns=2;i=16")
ip=icp.get_value()
icf=client.get_node("ns=2;i=15")
iff=icf.get_value()
ict=client.get_node("ns=2;i=17")
it=ict.get_value()
dcpp=client.get_node("ns=2;i=19")
dpp=dcpp.get_value()
dcff=client.get_node("ns=2;i=18")
dff=dcff.get_value()
dctt=client.get_node("ns=2;i=20")
dtt=dctt.get_value()
#Time=client.get_node("ns=2;i=3")
#Ti=Time.get_value()
#Ti1=datetime.time(Ti.hour,Ti.minute,Ti.second)
ti=datetime.now()
ti1=(str(ti.strftime('%Y-%m-%d %H:%M:%S')))
dt.append(str(Pressure)+','+ti1+','+str(ap)+','+str(r)+','+str(s)+','+str(n)+','+str(o)+','+str(h)+','+str(sps)+','+str(co)+','+str(dmp)+','+str(dmf)+','+str(chp)+','+str(cht)+','+str(ip)+','+str(it)+','+str(iff)+','+str(dpp)+','+str(dtt)+','+str(dff))
data['final']=dt
return JsonResponse(data)
Please check the getTemp() function as data is recieved from django in the success function. This is the part where you will have to make changes as per your requirement.
JS
<script type="text/javascript">
google.charts.load('current', {
callback: function () {
var chart = new google.visualization.LineChart(document.getElementById('graph'));
var options = {'title' : 'CTL-2 AIR PRESSURE (Bar)',
titleTextStyle: {
fontName: "Arial",
fontSize: 18,
},
animation: {
duration: 1000,
easing: 'out',
startup: true
},
hAxis: {
title: 'Time',
format: "HH:mm:ss",
textStyle: {
fontSize : 14,
bold:'true',
},
},
vAxis: {
title: 'Air Pressure',
format: '0.00',
textStyle: {
fontSize : 14,
bold:'true',
},
},
height: 450,
width:1000,
legend:'bottom'
};
var data = new google.visualization.DataTable();
data.addColumn('datetime', 'Time');
data.addColumn('number', 'Air Pressure');
var go=[];
function getTemp() {
$.ajax({
type:"get",
url:"{% url 'plcdata' %}",
success:function(dat){
for(i=0;i<dat.final.length;i++){
var go=dat.final[i].split(',');
var tm = new Date();
if(data.hg.length>15){
data.removeRow(0);
}
data.addRow([tm, Number(go[0])]);
chart.draw(data, options);
}
return dat;
},
error: function(){
console.log("Error Occurred");
}
})
}
getTemp();
setInterval(getTemp, 3000);
},
packages:['corechart']
});
</script>
[1]: https://i.stack.imgur.com/bMWVB.png
I do fear that similar questions have been asked in the past, however I was not able to derive a solution for my specific issue.
I am sending data from a Django function to Charts.js
The chart gets rendered correctly and displays with the exception of the date formatting on the X-Axis.
Django Data:
'''class UnitChartData(APIView):
def get(self, request, format=None):
material_code = request.session['material_code']
plant_code = request.session['plant_code']
qs_mat = DPoList.objects.filter(plant_code=plant_code).filter(material_code=material_code).order_by('delivery_date')
unit_price_list=[]
for items in qs_mat:
if items.gr_received is None or items.invoiced_usd is None:
unit_price = 0
unit_price_list.append(unit_price)
else:
unit_price=items.invoiced_usd/items.gr_received
unit_price_list.append(unit_price)
date_list=[]
for items in qs_mat:
date_list.append(items.delivery_date)
labels = date_list
default_items = unit_price_list
data = {
"labels": labels,
"default": default_items,
}
return Response(data)'''
Chart.js script
'''var endpoint = '/d/api/unitchart/data/'
var defaultData = []
var labels = [];
$.ajax({
method: "GET",
url: endpoint,
success: function(data){
labels = data.labels
defaultData = data.default
setChart()
},
error: function(error_data){
console.log("error")
console.log(error_data)
}
})
function setChart(){
var ctx = document.getElementById("myChart");
var myChart = new Chart(ctx, {
type: 'line',
data: {
labels: labels,
datasets: [{
label: 'PO#',
data: defaultData,
fill: false,
borderColor: [
'rgba(54, 162, 235, 1)',
],
borderWidth: 2
}]
},
options: {
responsive: true,
legend: {
position: 'bottom',
},
hover: {
mode: 'label'
},
scales: {
yAxes: [{
ticks: {
beginAtZero: false,
min: 2
}
}]
}
}
});
}'''
The Django Datetime object turns into an ISO date format: 2016-08-05T04undefined000Z - this is what gets displayed instead of just the month or date on the X-Axis.
I am trying to change that in the Javascript, either in the Charts.js or an additional function. from what I could find on Stackoverflow you can convert the date format through moments.js and in a second step set the xAxis to:
'''options: { scales: { xAxes: { type: 'time' } } }'''
However, I have not been ale to figure out how to do that and certainly not in an efficient way, any help would be greatly appreciated.
My HTML Canvas is like below :
<div>
<canvas id="chartdiv" width="200" height="200"></canvas>
</div>
Following is the json data,
[{
"SID": "1",
"NAME": "niten",
"FTEPERCENT": "71.29",
"FTCPERCENT": "28.71"
}, {
"SID": "2",
"NAME": "jiten",
"FTEPERCENT": "82.08",
"FTCPERCENT": "17.92"
}]
And below is the enter code :
window.onload = function() {
$.ajax({
type: "POST",
url: "ViewDirectManagersOverviewDetails.aspx/GetEmployeeOverviewDetailsForDirectManagers",
data: "{}",
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function(Result) {
debugger;
Result = JSON.parse(Result.d);
var newctx1;
for (var i = 0; i < Result.length; i++) {
var data1 = parseFloat(Result[i].FTEPERCENT);
var data2 = parseFloat(Result[i].FTCPERCENT);
var tempData = {
labels: ["FTE", "FTC"],
datasets: [{
data: [data1, data2],
backgroundColor: [
"#FF6384",
"#36A2EB"
],
hoverBackgroundColor: [
"#FF6384",
"#36A2EB"
],
borderWidth: 5
}]
};
// For a pie chart1
var ctx = document.getElementById("chartdiv").getContext("2d");
var myLineChart = new Chart(ctx, {
type: "pie",
data: tempData,
options: options,
title: {
display: true,
text: 'Employee Overview',
fontStyle: 'bold',
fontSize: 20
}
});
}
$('chartdiv').append(newctx1);
}
});
};
The above code is plotting pie chart on same canvas id but I want to plot to separate pie charts since json has two array objects but canvas id should be same.
Looping through json will give two separate objects so I will have to draw in table two separate pie chart the way we show data in datatable similarly need to show pie charts in table rows.
Unfortunately, there is no way to render multiple charts within a single canvas. Chart.js binds to the entire canvas object and uses the full canvas to render a single chart.
If you want to see two separate pie charts then you need two separate canvas elements. However, you can of course add multiple datasets to a single graph if that suites your needs. For the pie chart it will embed a smaller pie chart within a larger one.
Here is an example config that shows how to setup multiple datasets in a single pie chart.
var ctx = document.getElementById("chart-area").getContext("2d");
var myPie = new Chart(ctx, {
type: 'pie',
data: {
labels: ["FTE", "FTC"],
datasets: [{
label: 'Dataset 1',
data: data1,
backgroundColor: [
"#FF6384",
"#36A2EB"
],
hoverBackgroundColor: [
"#FF6384",
"#36A2EB"
],
borderWidth: 5,
}, {
label: 'Dataset 2',
data: data2,
backgroundColor: [
"#FF6384",
"#36A2EB"
],
hoverBackgroundColor: [
"#FF6384",
"#36A2EB"
],
borderWidth: 5,
}],
},
options: {
title: {
display: true,
text: 'Employee Overview',
fontStyle: 'bold',
fontSize: 20
}
}
});
Here is a codepen example to demonstrate this.