I'm not really good in javascript, a language I always have difficulties to understand and work with. I'm working on a Django project where I need to pass a list to Chart.js to display a graph according to a specific Model.
The problem I have is trying to pass a list to javascript from Django in order to display data if they are available or not.
Let's say I have a python list from a Model attribute :
[10, 20, None, 30, 40, None, 50]
I need Chart.js to display data depending if they is a value for each axis point and nothing if they is None. When I try to pass the list with json.dump() and then in my template with {{ my_list|safe }} it display it like this :
['10', '20', 'None', '30', '40', 'None', '50']
Everything is diplayed as str when it should be either int or None/null value. How should I do if I need chart.js to have values as they are in backend ?
Hoping my problem is clear enough, if not let me know and I'll try to better explain !
Thank you in advance for your precious help.
Chart.js code
var ctx = document.getElementById('financial-chart');
var myChart = new Chart(ctx, {
type: 'line',
data: {
labels: {{ tab_year|safe }}",
datasets:
[{
label: 'Sales',
data: {{ tab_sales|safe }},
backgroundColor: "#4C81B6",
borderColor: "#4C81B6",
borderWidth: 3,
tension: 0.3,
fill: false
},
{
label: 'Profit',
data: {{ tab_profit|safe }},
backgroundColor: "#DF5558",
borderColor: "#DF5558",
borderWidth: 3,
tension: 0.3,
fill: false
}]
},
options: {
scales: {
y: {
beginAtZero: true
}
}
}
});
SOLVED
As mentionned by elyas the extra quotation mark was the reason causing the issue. Nones are now interpreted as null as they should be.
Related
I have two line graphs, the first is working fine and the second is just 3 points that lies on top of the first one to signify the main peak point, the peak to the left, and the peak to the right. I am passing in a value and labels array for the original line graph, and that works fine. I am also passing in a values2 and a labels2 array for the peak points. These values are correct. Both are float values and both look something like this below, with different values each time obviously
values2 = [-76.334, -90.648, -89.625]
labels2 = [1.83, 1.93546, 1.76815]
this is my chartjs code from my html file
<div id="canvas-holder">
<canvas id="myChart" width="800" height="300"></canvas>
</div>
<script>
var options = {
type: 'line',
data: {
labels: {{ labels | safe }},
datasets: [{
label: 'Value',
data: {{ values | safe }},
backgroundColor: 'white',
borderWidth: 1,
order: 2
},
{
label: 'Peak value',
data: [{
x: {{ labels2[0] | safe }},
y: {{ values2[0] | safe }}
}, {
x: {{ labels2[1] | safe }},
y: {{ values2[1] | safe }}
}, {
x: {{ labels2[2] | safe }},
y: {{ values2[2] | safe }}
}],
backgroundColor: 'black',
borderWidth: 5,
pointRadius: 5,
showLine: false,
order: 1
}
]
},
options: {
responsive: true,
scales: {
xAxes: [{
ticks: {
beginAtZero: true
}
}]
}
}
};
var ctx = document.getElementById('myChart').getContext('2d');
new Chart(ctx, options);
If I'm understanding chartjs correctly, I believe that this should be working. Each value is mapped to it's corresponding x and y values, I'm not sure what's wrong with this. I would appreciate any help.
For anybody in the future, I found that switching to an older version of chartjs made this work. I don't know if there's a new way to plot two graphs or what but I switched to version 2.9.X and it worked
Looking for some help here. The doughnut chart is rendering properly, but all the colors are gray. I've scoured the chartjs site and googled, but I can't seem to solve this.
Here's my code:
#app.route('/doughnut_chart')
def doughnut_chart():
values = []
labels =['good', 'mediocre','bad']
colors = ['rgba(0, 153, 0, 0.1)', 'rgba(0,153,153,0.1)','rgba(102,153,51,0.1)']
good_high = db.session.query(func.sum(Jf_Q1.highwellbeing)/func.sum(Jf_Q1.good_job)).\
filter(Jf_Q1.working==1).filter(Jf_Q1.good_job==1)
good_mod = db.session.query(func.sum(Jf_Q1.moderatewellbeing)/func.sum(Jf_Q1.good_job)).\
filter(Jf_Q1.working==1).filter(Jf_Q1.good_job==1)
good_low = db.session.query(func.sum(Jf_Q1.lowwellbeing)/func.sum(Jf_Q1.good_job)).\
filter(Jf_Q1.working==1).filter(Jf_Q1.good_job==1)
values = [0.82483097725875845114*100,0.14935464044253226798*100,0.01966810079901659496*100]
return render_template('results.html', values=values,labels=labels, colors=colors)
and my script code on the web page:
new Chart(document.getElementById("doughnut-chart"), {
type: 'doughnut',
data: {
labels : {{labels | safe}},
backgroundColor: {{colors | safe}},
datasets:
[{ data : {{values | safe}}
}]
},
options: {
title: {
display: true,
text: 'Doughnut Chart Title'
}
}
});
Here's how it looks in Chrome's inspector:
new Chart(document.getElementById("doughnut-chart"), {
type: 'doughnut',
data: {
labels : ['good', 'mediocre', 'bad'],
backgroundColor: ['rgba(0, 153, 0, 0.1)', 'rgba(0,153,153,0.1)', 'rgba(102,153,51,0.1)'],
datasets:
[{ data : [82.48309772587584, 14.935464044253226, 1.9668100799016592]
}]
},
options: {
title: {
display: true,
text: 'Doughnut Chart Title'
}
}
});
I've tried hex colors such as:
backgroundColor: ["#3e95cd", "#8e5ea2","#3cba9f","#e8c3b9"]
But still no dice
This is what is looks like in Chrome and in FF:
my chart
Any assistance is greatly appreciated.
Thanks
Fixed it!. datasets is a list of objects. I needed to place the backgroundColor option inside datasets as such:
datasets:
[{ data : [82.48309772587584, 14.935464044253226, 1.9668100799016592],
backgroundColor: ['rgba(0, 153, 0, 0.1)', 'rgba(0,153,153,0.1)', 'rgba(102,153,51,0.1)'],
fill: true
}],
I had it outside. RTFM! lol
$(function() {
$('#container').highcharts({
chart: {
type: 'heatmap',
marginTop: 40,
marginBottom: 80,
plotBorderWidth: 0.5
},
title: {
text: 'Number'
},
xAxis: {
categories: [ .......... ]
},
yAxis: {
categories: [ .......... ],
title: null
},
colorAxis: {
min: 0,
minColor: '#FFFFFF',
maxColor: Highcharts.getOptions().colors[0]
},
legend: {
align: 'right',
layout: 'vertical',
margin: 0,
verticalAlign: 'top',
y: 25,
symbolHeight: 280
},
tooltip: {
formatter: function() {
return '' +
this.series.xAxis.categories[this.point.x] +
'<br>' +
this.series.yAxis.categories[this.point.y] +
'<br>' + this.point.value;
}
},
series: [{
name: 'Sales per employee',
borderWidth: 1,
data: [ .......... ],
http://jsfiddle.net/Slate_Shannon/0mvgmhLb/6/
This is a heatmap chart. The chart looks okay as-is, but should have more data. However, if I add any additional data, the chart breaks.
Note that a large part of the data is commented out. This starts with the data that begins with
[50,0,null],
[50,1,8380],
[50,2,37430],
(note that I removed the axis labels and the data in the code shown above.)
If you change the position of the beginning of the comment tag to so that the "50" data gets charted, then the chart fails.
Is this just too much data, or is there a way to create a heatmap that needs to be approx 20 x 90 cells?
Set turboThreshold to 0, from the Highcharts API:
When a series contains a data array that is longer than this, only one dimensional arrays of numbers, or two dimensional arrays with x and y values are allowed. Also, only the first point is tested, and the rest are assumed to be the same format. This saves expensive data checking and indexing in long series. Set it to 0 disable. Defaults to 1000.
http://api.highcharts.com/highcharts/plotOptions.heatmap.turboThreshold
Example: http://jsfiddle.net/0mvgmhLb/7/
series: [{
name: 'Sales per employee',
borderWidth: 1,
turboThreshold: 0,
...
Try loading the Highcharts Boost module.
The boost.js module is a module to allow quick loading of hundred
thousands of data points in Highcharts.
Instead of relying solely on SVG to display the graph, this module does the following to boost performance:
... drawing the graph on a canvas, then copying over the contents to
an image tag inside the SVG, using a data URL.
Link to official blog post.
Just load the module after highcharts.js (lib/modules/boost.js).
This can be solved by providing the colorAxis with a min and max value. Highcharts has issues with calculating the max value with extremely large data sets.
I'm using Chart.js to create a line chart. I would like to have four different datasets that will all be visibile by default, but can be toggled on and off by clicking a button. How can this be achieved? I can't seem to find an answer in the documentation. .addData(), .removeData() and .update() all seem to be used for adding or removing values to existing datasets, but not adding or removing entire datasets. I would think this would be fairly commonly used feature but I can't find an answer anywhere.
After thoroughly researching this, there doesn't appear to be any built in function to toggle entire datasets. I used the .destroy() function to remove the entire existing chart, and then some logic to redraw it with the necessary datasets.
EDIT: Here's a fiddle with my full code if it's helpful to anyone -> http://jsfiddle.net/21xg27kr/4/
Here is a line chart with two datasets. By updating the datasets and calling the .update() method. The benefit here is you don't need to destroy the whole chart, and there is a nice animated transition which can be disabled.
TL:DR; solution on jsfiddle
Step by Step:
Bring in Chart.js from a CDN
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.5.0/Chart.min.js"></script>
Create the HTML Canvas element that will hold the chart
<canvas id="line-chart"></canvas>
Hide/Show buttons for this example
Creating the chart, and the functions to update it live - notice that the same integer data needs to be copied in two places - in the initial creation, and in the show function.
<script>
lineChart = new Chart(document.getElementById("line-chart"), {
type: 'line',
data: {
labels: ['A', 'B', 'C', 'D'],
datasets: [
{
label: "Set 1",
fill: true,
backgroundColor: "rgba(90,181,242,0.2)",
borderColor: "rgba(179,181,198,1)",
pointBorderColor: "#fff",
pointBackgroundColor: "rgba(179,181,198,1)",
data: [3, 1, 1, 0]
}, {
label: "Set 2",
fill: true,
backgroundColor: "rgba(255,99,132,0.2)",
borderColor: "rgba(255,99,132,1)",
pointBorderColor: "#fff",
pointBackgroundColor: "rgba(255,99,132,1)",
pointBorderColor: "#fff",
data: [1, 3, 3, 5]
}
]
},
options: {
title: {
display: true,
text: 'Chart Title'
}
}
});
function restoreLayer2(){
lineChart.data.datasets[1].data = [1, 3, 3, 5];
lineChart.update();
}
function removeLayer2() {
lineChart.data.datasets[1].data = [];
lineChart.update();
}
</script>
I'm trying to update a point[x,y] in the chart.
What's the problem?
Ok, I chart and its chart series are like this:
series: [
{
enableMouseTracking: false,
name: 'Line1',
type: 'line',
color: '#5d5d5d',
yAxis: 1,
data: [[12000, 55.068493], [15064, 42.842]],
marker: {
symbol: 'circle'
}
},
{
enableMouseTracking: false,
name: 'Line2',
type: 'line',
color: '#5d5d5d',
yAxis: 1,
marker: {
symbol: 'circle'
},
data: [[12000, 57.671527], [16000, 42.620069]]
},{
name: 'TOM',
//type: 'line',
color: '#ff4100',
yAxis: 1,
marker: {
symbol: 'url(icons/tom.png)'
},
data: [
{
id:'tom_point',
color: '#00FF00',
y: fi_variable,
x: tom_variable
}
]
}
Now the thing is that, I'm checking if fi_variable or tom_variable has changed and if its true, update these two variables, and finally update the chart.
I have tried already, some methods like chart.series[0].data[0].update(y = 10); and its working for some points with fixed x,y values, but no luck for the rest of the points.
For Instance I use chart.series[0].data[1].update(y = 10); will work ok,
but this chart.series[0].data[3].update(y = 10); will not work.
1- Is there any way to replace the data[0] from the above code line with an id of a point in our case tom_point ?
Also I've tried this chart.series[0].setData([[tom_variable,fi_variable, 'tom_point']]);
and again it wont working when the point is with an id or without fixed values.
But If I try chart.series[0]data[0].setData([[tom_variable,fi_variable]]); it works but again not on 3rd element (in our case - as shown above) of the series.
I can get the values for this point with the following,
var tomPoint = chart.get('tom_point').y;
but I can't set any x,y values back to chart and update it (the chart).
I have also tried to check if the variables have changed and to redraw the chart with chart.redraw but nothing.
Any Ideas how can I get this to work?
Am I losing something?
Thank you in Advance for your time.
First of all you try to update point (data[3]) which doens't exist in serie. Secondly in case when you update you need to use
chart.series[0].data[1].update(10); or chart.series[0].data[1].update({y:10}); but not yoru figure
if you want to change the x value also then use
chart.series[0].data[0].update({
x: 10,
y: 100
})
this will update both x and y values like in this example http://jsfiddle.net/DCA8W/
Hope this is what you are looking for.
Ok, the solution finally was simple.
I've managed to update the point:
The third element in the series with the name TOM corresponds to
chart.series[2].
{ // chart.series[2]
name: 'TOM',
//type: 'line',
color: '#ff4100',
yAxis: 1,
marker: {
symbol: 'url(icons/tom.png)'
},
data: [
{
id:'tom_point',
color: '#00FF00',
y: fi_variable,
x: tom_variable
}
]
}
So in order to update [x,y] values of this point, you have to do it like that:
// TOM Point
`chart.series[2].data[0].update({x:var_x, y:var_y});`