ChartJS doesnt display labels provided by Jinja variable - flask

I would like to use Flask to render a ChartJS graph. This is from my routes.py
#app.route("/graph")
def graph():
d = Eval.query.all()
labels = [i.date.strftime('%d.%m.%Y') for i in d]
data = [i.bw for i in d]
return render_template('chart.html', title='Charts', labels = labels, data = data)
I've the following code in the chart.html:
{% extends "base.html" %}
{% block content %}
<canvas id="myChart" height="400" width="800"></canvas>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.4.0/Chart.min.js"></script>
<script type="text/javascript">
var ctx = document.getElementById('myChart').getContext('2d');
var chart = new Chart(ctx, {
type: 'line',
data: {
labels: ['16.07.2017', '23.07.2017', '30.07.2017', '06.08.2017', '13.08.2017'],
datasets: [{
label: "My First dataset",
backgroundColor: 'rgb(255, 99, 132)',
borderColor: 'rgb(255, 99, 132)',
data: {{ data }}
}]
},
options: {
responsive:false
}
});
</script>
{% endblock %}
with this code the chart is rendered with the correct labels.
Question:
However once I change the labels to
labels: {{ labels }}
the chart is not rendered at all.
I checked to make sure that the {{ labels }} expression is indeed also a list with the correct formating. Calling {{ labels }} above the script tag shows the following output in the html page:
['16.07.2017', '23.07.2017', '30.07.2017', '06.08.2017', '13.08.2017']

If you are not using safe filter special symbols would be escaped during template parsing process and would corrupt the variable value.
In the case above, final variable value without 'jinja safe' filter would be
["16.07.2017", "23.07.2017"] =>['16.07.2017','23.07.2017']
And that value (['16.07.2017','23.07.2017']) is illegal for JS and you'll be able to see the error in the browser console:
Uncaught SyntaxError: Unexpected token &
In the case above, final variable value with 'jinja safe' filter would be the same
["16.07.2017", "23.07.2017"] =>["16.07.2017", "23.07.2017"]
You can read more about escaping here.

var ctx = document.getElementById('myChart').getContext('2d');
var dates = {{labels|safe}};
var data1 = {{data|safe}}
var chart = new Chart(ctx, {
type: 'line',
data: {
labels: dates,
datasets: [{
label: "My First dataset",
backgroundColor: 'rgb(255, 99, 132)',
borderColor: 'rgb(255, 99, 132)',
data: data1
I added the Jinja expressions as variables inside the script and now the chart renders as expected. Still not sure why ...

Related

ChartJS change background color by conditions

Any idea how to change background colours to a Column in ChartJS, based on numbers on the horizontal axis? The result required is like the image bellow.
Eg.
horizontal axis between 0 - 2, background color for those columns is '#000'
horizontal axis between 3 - 4, background color for those columns is '#eee'
horizontal axis equal or greater then 5, background color for those columns is '#888'.
See Print Example
If I'm understanding correctly you want to be able to colour each individual column. If you put all the data in the same dataset you can use backgroundColor as below to define a colour order.
HTML:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<script src='https://cdn.jsdelivr.net/npm/chart.js#3.7.1/dist/chart.min.js'></script>
</head>
<body style="background:black">
<div class="chart-container">
<canvas id="myChart"></canvas>
</div>
</body>
</html>
JS:
const ctx = document.getElementById('myChart').getContext('2d');
this.MYCHART = new Chart(ctx, {
type: "bar",
data: {
labels: ['0', '1', '2', '3', '4'],
datasets: [{
data: [100, 100, 100, 100, 100],
backgroundColor: [
'#FFF',
'#FFF',
'#eee',
'#eee',
'#888',
]
}]
}
});

Charts.js is automatically adding comma as thousands separator when it shouldn't

Charts.js is abusively adding comma separator between thousands while is nowhere set to do this. To all floats. To the axis, labels, tooltips, everywhere possible and on all types of charts.
I am in EU, so the computer, browser, locales have nothing to do with EN/US. Nowhere in the code is specified to add these commas to numbers.
The underlying data does not contain commas either:
[{continent:"Africa",value:14802.32},{continent:"Asia",value:6783.37},...]
This is very annoying, unacceptable for my (French) customer.
Is it a bug ? Or please be kind and provide the way how to remove comma everywhere.
You must be doing something wrong because by default the data is seperated by dots, so you must have specified it somewhere. But you can configure it by using the locale property:
var options = {
type: 'line',
data: {
labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"],
datasets: [{
label: '# of Votes',
data: [12000.5, 19000, 3000, 5000, 2000, 3000],
borderColor: 'pink'
}]
},
options: {
//locale: 'en-EN' // Uncomment this line for "wrong" options
}
}
var ctx = document.getElementById('chartJSContainer').getContext('2d');
new Chart(ctx, options);
<body>
<canvas id="chartJSContainer" width="600" height="400"></canvas>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.5.1/chart.js"></script>
</body>

django chart.js can't use {{% for loop%}}

I am a newbie to django, I don’t know why I can use for loop in javascript in other people’s teaching, but I can’t use for loop in javascript like this. Hope someone can tell me why.
<script>
var ctx = document.getElementById('myChart').getContext('2d');
var myChart = new Chart(ctx, {
type: 'bar',
data: {
labels: [{% for i in myobject %}"{{ labels }}",{% endfor %}],
datasets: [{
label: '# of Votes',
data: '{{ data }}',
}]
},
});
</script>

grouped bar dataset in djanog template loop

i would like to draw a grouped bar from chart js using django which currently works fine. Actually i do manually. but i need to draw a grouped bar through for loop(data,label,background-color).
Actual
label_list=[2019,2020]
color_list=['#e75e72','#3396ff']
data_list=[[282,314,106,502,107,111],[86,350,411,340,635,809]]
datasets: [
{
label: {{label_list.0|safe}},
backgroundColor: '{{color_list.0|safe}}',
data:{{data_list.0|safe}} ,
},
{
label: {{label_list.1|safe}},
backgroundColor: '{{color_list.1|safe}}',
data: {{data_list.1|safe}} ,
},
]
i really do not have any idea to make it dynamically.
i need something like
{% for x in label_list %}
{{
label:label_list.forloop.counter[x],
background-color:color_list.forloop.counter[x],
data:data_list.forloop.counter[x]
}}//forloop.counter0,forloop.counter1
{% endfor %}
thanx in advance.
Rather than processing the values in template, why not you build the dataset in view and send it as context, like this:
datasets = list()
for label, color, data in zip(label_list, color_list, data_list):
value_dict = {
'label': label,
'backgroundColor' : color,
'data': data
}
datasets.append(value_dict)
context = {'datasets': json.dumps(datasets)} # use 'import json' on top of the file
return render('template.html', context)
Then use it directly in your template like this:
<script>
var dataset = {{ datasets }}
// rest of the code
</script>

google line chart points manipulation based on series value

I am using Google Line Chart for my project. I need to manipulate points on the line chart based on the values. For example, if the value is less then 170 then it shows default point on line chart and if it is greater then 170, it should show different point on the line chart. how should i put different color for points in the line chart for one series? Here is my code:
<html>
<head>
<script type="text/javascript" src="https://www.google.com/jsapi"></script>
<script type="text/javascript">
google.load("visualization", "1", {packages:["corechart"]});
google.setOnLoadCallback(drawChart);
function drawChart() {
var data = google.visualization.arrayToDataTable([
['Date', 'Record'],
['4/1', 165],
['4/2', 160],
['4/3', 163],
['4/4', 173]
]);
var options = {
title: 'Line Chart', pointSize : 5 };
var chart = new google.visualization.LineChart(document.getElementById('chart_div'));
chart.draw(data, options);
}
</script>
</head>
<body>`enter code here`
<div id="chart_div" style="width: 900px; height: 500px;"></div>
</body>
</html>
Plese help me on this.
You cannot color points individually using the current Google Visualization API. Any coloring must be done with separate series.
In your case, you can achieve the desired result with a workaround. Here is what I presume you want:
This code should give you the result you want:
<html>
<head>
<script type="text/javascript" src="https://www.google.com/jsapi"></script>
<script type="text/javascript">
google.load("visualization", "1", {packages:["corechart"]});
google.setOnLoadCallback(drawChart);
function drawChart() {
var data = new google.visualization.DataTable();
data.addColumn('string', 'Date');
data.addColumn('number', 'Line');
data.addColumn('number', 'Under 170');
data.addColumn('number', 'Over 170');
data.addRows([
['4/1', 165, 165, null],
['4/2', 160, 160, null],
['4/3', 163, 163, null],
['4/4', 173, null, 173]
]);
var options = {
title: 'Line Chart',
pointSize : 5,
series: [{color: 'black', pointSize: 0}, {color: 'red', lineWidth: 0}, {color: 'blue', lineWidth: 0}]
};
var chart = new google.visualization.LineChart(document.getElementById('chart_div'));
chart.draw(data, options);
}
</script>
</head>
<body>`enter code here`
<div id="chart_div" style="width: 900px; height: 500px;"></div>
</body>
</html>
Basically, what you have to do is:
Create 3 different series
One for the line (no points shown)
One for the points <170 (color 1)
One for the point >=170 (color 2)
Add all data values to series 1 (so there is a solid line)
Add points to series 2 that are <170, with all other values as null
Add points to series 3 that are >=170, with all other values as null
You can then use the series option to format the chart. The first series will determine the line color. The second series will determine the color for points <170. The third series will determine the color for point >=170.