Charts.js + Django date on X-Axis - javascript

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.

Related

Chart JS Displays Only Bigger Dataset But Has Both Datasets?

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.

Python to chart.js

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

Chart data isnt showing in the canvas but console.log shows the expected values

So its my first time using chartjs. Im trying to use stacked horizontal charts. I have 2 values which I calculate using some sort function. I do console.logs to check if values are correct and they are both as expected. But when i try to update the chart only the first value shows in the canvas, and the 2nd value shows 0 but my chart gridlines adjusts correctly. Im not too sure what is happening.
Here is where I declare my chart data
var eventDays1 = 0;
var eventDays2 = 0;
var barChartData = {
labels: ['Events'],
datasets: [{
label: eventName1,
backgroundColor: "#E5C1BD",
data:[eventDays1]
}, {
label: eventName2,
backgroundColor: "#D2D0BA",
data:[eventDays2]
}
]};
Here is the actual chart
myBarChart = new Chart(ctx, {
type: 'horizontalBar',
data: barChartData,
options: {
legend: {
display: true,
labels: {
fontColor: 'black',
fontSize:20,
}
},
responsive: true,
scales: {
xAxes: [{ stacked: false,
ticks:{
fontColor:"black"
},
scaleLabel: {
display: true,
labelString: 'Days',
fontColor:"black"
}
}],
yAxes: [{
ticks: {
beginAtZero:true,
max:365,
fontColor:"black"
},
stacked: true,
}]
}
},
});
Here is my updateChart function that I call. Note that the console.logs
are values that I expect already.
function updateChart(newList){
eventDays1 = newList[0];
if(newList.length == 2){
eventDays2 = newList[1];
}
myBarChart.data.datasets[0].data[0] = eventDays1;
myBarChart.data.datasets[0].data[1] = eventDays2;
console.log("data 1 "+eventDays1);
console.log("data 2 "+eventDays2);
myBarChart.update();
}

How can I plot data from an external JSON file to a chart.js graph?

I would like to chart data from an external JSON file using chart.js. As an example, the json file here lists movies ("title") and ratings ("rt_score"). I'd like to be able to show each movie and its rating without including the static JSON in the .js file, but rather using the $.ajax call method to refer to the /films endpoint.
I'd like to have:
labels: labelsVariable
data: dataVariable
Here is a fiddle with the setup so far with static data.
Here's my HTML:
<body>
<canvas id="myChart" width="400" height="400"></canvas>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.8.0/Chart.min.js">
</script>
</body>
Here's the js that successfully generates a bar chart like I want, but with static data in "labels" and "data" instead of referencing the JSON file.
var ctx = document.getElementById('myChart');
var myChart = new Chart(ctx, {
type: 'bar',
data: {
labels: ['Castle in the Sky', 'Grave of the Fireflies'],
datasets: [{
label: 'rating',
data: [95, 97],
borderWidth: 1
}]
},
options: {
scales: {
yAxes: [{
ticks: {
beginAtZero: true
}
}]
}
}
});
Instead of using the static data and labels, how can I reference the external JSON file using the $.ajax call method?
Based on what I've read, I may have to use "map" to break down the objects into arrays that contain labels and data?
Thank you in advance.
I think you are looking for Ajax request to fill your chart.
function getRandomIntInclusive(min, max) {
min = Math.ceil(min);
max = Math.floor(max);
return Math.floor(Math.random() * (max - min + 1)) + min;
}
var ctx_live = document.getElementById("mycanvas");
var myChart = new Chart(ctx_live, {
type: 'bar',
data: {
labels: [],
datasets: [{
data: [],
borderWidth: 1,
borderColor:'#00c0ef',
label: 'liveCount',
}]
},
options: {
responsive: true,
title: {
display: true,
text: "Chart.js - Dynamically Update Chart Via Ajax Requests",
},
legend: {
display: false
},
scales: {
yAxes: [{
ticks: {
beginAtZero: true,
}
}]
}
}
});
var postId = 1;
var getData = function() {
$.ajax({
url: 'https://jsonplaceholder.typicode.com/posts/' + postId + '/comments',
success: function(data) {
myChart.data.labels.push("Post " + postId++);
myChart.data.datasets[0].data.push(getRandomIntInclusive(1, 25));
// re-render the chart
myChart.update();
}
});
};
setInterval(getData, 3000);
see live example here.
Load the json chart data dynamically and set it when you are creating the graph. There are many ways you can load the chart json data. However, I believe the JQuery getJSON function is more relevant to you.
$.getJSON( "chartdata/test.json", function( data ) {
var myChart = new Chart(ctx, {
type: 'bar',
data: data,
options: {
scales: {
yAxes: [{
ticks: {
beginAtZero: true
}
}]
}
}
});
}
I figured it out. Here's what worked. I had to use .map to set up the data properly inside variables and then use those variables as data and labels.
function renderChart(data, labels) {
var ctx = document.getElementById("myChart").getContext('2d');
var myChart = new Chart(ctx, {
type: 'bar',
data: {
labels: labels,
datasets: [{
label: 'This week',
data: data,
}]
},
});
}
function getChartData() {
$("#loadingMessage").html('<img src="./giphy.gif" alt="" srcset="">');
$.ajax({
url: "https://ghibliapi.herokuapp.com/films",
success: function (result) {
var data = result.map(x=>x.rt_score);
var labels = result.map(x=>x.title);
renderChart(data, labels);
console.log(data);
},
});
$("#renderBtn").click(
function () {
getChartData();
});

Chart.js with Django - Using REST

Using Django rest frame work i have my query set-up and pulling my data to a url like below. I'm trying to get the data in to chart.js. I can manage to get it to the console or plot the first result, but no further any assistance would be greatly appreciated
"comp_history_data": [
[
"(2017, 01, 20)",
256.0
],
[
"(2018, 01, 20)",
456.0
],
[
"(2018, 02, 20)",
568.0
],
[
"(2018, 03, 20)",
683.0
]
],
Here is what i have in my HTML, works fine with dummy data, just not too sure how to plot with the data above
<script>
var endpoint = '/api/chart/data/'
var defaultData = []
var labels = [];
$.ajax({
method: "GET",
url: endpoint,
success: function(data){
labels = data.labels
defaultData = data.comp_history_data.forEach(functoin(entry){
console.log(entry)
setChart()
},
error: function(error_data){
console.log("error")
console.log(error_data)
}
})
function setChart(){
var ctx = document.getElementById("myChart").getContext('2d');
var myChart = new Chart(ctx2, {
type: 'line',
data: {
labels: labels,
datasets: [{
label: '# of Computers',
data: defaultData,
backgroundColor: [
'rgba(255, 99, 132, 0.2)',
],
borderColor: [
'rgba(255,99,132,1)',
],
borderWidth: 1
}]
},
options: {
scales: {
yAxes: [{
ticks: {
beginAtZero:true
}
}]
}
}
});
}
</script>
Small Edit: I can get one item onto the graph with the code below, so looks like the data is coming through OK, just need to separate
<script>
var endpoint = '/api/chart/data/'
var defaultData = []
var labels = [];
$.ajax({
method: "GET",
url: endpoint,
success: function(data){
labels = data.labels
defaultData = data.comp_history_data.forEach(functoin(entry){
console.log(entry)
setChart()
},
error: function(error_data){
console.log("error")
console.log(error_data)
}
})
function setChart(){
var ctx = document.getElementById("myChart").getContext('2d');
var myChart = new Chart(ctx2, {
type: 'line',
data: {
labels: labels,
datasets: [{
label: '# of Computers',
data: defaultData[0],
backgroundColor: [
'rgba(255, 99, 132, 0.2)',
],
borderColor: [
'rgba(255,99,132,1)',
],
borderWidth: 1
}]
},
options: {
scales: {
yAxes: [{
ticks: {
beginAtZero:true
}
}]
}
}
});
}
</script>
Any thoughts on how i use the data array i have with chart.js I would like the 0 the data to be along the bottom with the numbers plotted on the graph
Thanks again
Remember to include <canvas id="myChart"></canvas> within your html file.
That might be all you need. If not, this is a working function I have - I've not changed my variable names to match your's but I think it easy to understand.
success : function(json) {
// Add graph
var chartLabels = json.categories.map(function(e) {
return e.name;
})
var chartValues = json.values.map(function(e) {
return e;
})
var ctx = document.getElementById("myChart");
var data = {
labels: chartLabels,
datasets: [{
"label" : json.startRegulation[0].name,
"data" : chartValues,
"fill" : true,
"backgroundColor":"rgba(255, 99, 132, 0.2)",
"borderColor":"rgb(255, 99, 132)",
"pointBackgroundColor":"rgb(255, 99, 132)",
"pointBorderColor":"#fff",
"pointHoverBackgroundColor":"#fff",
"pointHoverBorderColor":"rgb(255, 99, 132)"
}]
}
var options = {
"elements":
{"line":{"tension":0,"borderWidth":3}
},
scale : {
ticks : {
min : 0,
}
}
}
var myChart = new Chart(ctx, {
type: 'radar',
data: data,
options : options,
});
Try to change :
defaultData = data.comp_history_data.forEach(functoin(entry){
to :
defaultData = data.comp_history_data.forEach(function(entry)){
Also, read the usage of template filters (Django) maybe you will find them helpful.
For instance, from your views.py file send data :
def MyView(request):
comp_history_data: ['1', '2', '3']
return render(request, 'chart.html', {'comp_history_data':comp_history_data})
and then in your HTML file print the vars :
{% for var in comp_history_data %}
{{ var }}
{% endfor %}
Hope it helps
It looks like you have an error in your success function, as below
defaultData = data.comp_history_data.forEach(functoin(entry){
to:
defaultData = data.comp_history_data.forEach(function(entry){

Categories

Resources