Django resize chart in table - django

I have a basic chart created with chart.js which is later displayed in table. I have a problem to manipulate his height/width to fit it correctly to table in django template. Chart is displayed in for loop in table and code looks like:
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.3/Chart.min.js"></script>
<table class="table table-bordered">
<thead>Details
</thead>
<tbody>
{% for key, value in game_details.items %}
<tr>
<th>Game</th>
<th>Played</th>
<th>Won</th>
<th>Lost</th>
<th>Pending</th>
</tr>
<tr>
<td>Game </td>
<td>{{ value.all }}</td>
<td>{{ value.win }}</td>
<td>{{ value.lost }}</td>
<td>{{ value.pending }}</td>
</tr>
<tr>
<td colspan="5" style="max-height: 10px">
<canvas id="myChart{{ key }}" width="200" height="200"></canvas>
<script>
const ctx{{ key }} = document.getElementById('myChart{{ key }}').getContext('2d');
const myChart{{ key }} = new Chart(ctx{{ key }}, {
type: 'doughnut',
data: {
labels: ['W', 'L', "P"],
datasets: [{
label: '# of Votes',
data: [{{ value.win }}, {{ value.lost }}, {{ value.pending }}],
backgroundColor: [
'rgba(255, 99, 132, 0.2)',
'rgba(54, 162, 235, 0.2)',
'rgba(153, 102, 255, 0.2)',
],
borderColor: [
'rgba(255, 99, 132, 1)',
'rgba(54, 162, 235, 1)',
'rgba(153, 102, 255, 1)',
],
borderWidth: 1
}]
},
options: {
scales: {
y: {
beginAtZero: true
}
}
}
});
</script>
</td>
</tr>
{% endfor %}
</tbody>
</table>
and it looks like that:
Changing the width or height in canvas element doesn't change any size. Is there any solution I can fit it to table so this will look more user friendly?

Related

Django chart.js multi axis line chart

Hi Guys I have inspired from this Fiddle example to try to create a similar multi axis line chart in my django project.
I have in my views :
class dashboard(TemplateView):
template_name = 'users/dashboard.html'
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['qs'] = DummyData.objects.all()
data = DummyData.objects.all()
years=[]
for i in range(data.count()) :
if data[i].year not in years :
years.append(data[i].year)
context['years'] = years
return context
in in my dashboard.html :
{% extends 'users/base.html' %} {% load static %} {% block content %}
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- semantic UI -->
<link rel="stylesheet" type='text/css' href="https://cdnjs.cloudflare.com/ajax/libs/semantic-ui/2.2.14/semantic.min.css">
<!--Chart js-->
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.8.0/Chart.min.js" integrity="sha256-Uv9BNBucvCPipKQ2NS9wYpJmi8DTOEfTA/nH2aoJALw=" crossorigin="anonymous"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.8.0/Chart.min.css" integrity="sha256-aa0xaJgmK/X74WM224KMQeNQC2xYKwlAt08oZqjeF0E=" crossorigin="anonymous" />
<!-- jQuery -->
<script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
<script>
$(document).ready(function (){
var ctx = document.getElementById('myChart');
var myChart = new Chart(ctx, {
type: 'line',
data: {
labels: [{% for year in years %} '{{year}}', {% endfor %}],
datasets: [{% for item in qs %}
{
label: '{{item.site}}',
yAxisID: '{{item.site}}',
data: [100, 96, 84, 76, 69] , {% endfor %}
]
},
options: {
scales: {
yAxes: [{
id: 'A',
type: 'linear',
position: 'left',
}, {
id: 'B',
type: 'linear',
position: 'right',
ticks: {
max: 1,
min: 0
}
}]
}
}
});
});
</script>
<canvas id="myChart" width="400" height="100"></canvas>
{% endblock content %}
When I copied the fiddle example it showed correctly in my dahsboard.html as follows :
But When I tried to change the datasets in the code as presented in my dashboard.html nothing shows up, labels are updated okay but this is what makes my chart not work :
datasets: [{% for item in qs %}
{
label: '{{item.site}}',
yAxisID: '{{item.site}}',
data: {{item.turn_over}}' , {% endfor %}
]
I am sure this is not how it is supposed to be done, I'm a beginner at chart.js , what I want to do is load how many sites I have in my Dummydata table and show their turn over
Thank you
Done It was a comma positioning mistake, I checked the console and the problem was that when my if condition was not being checked instead of skipping, it was adding an empty value, meaning that I was getting for example 1, , , , 2 , , , 3 instead of 1,2,3 and the chart was rendering the empty cells, anyway here is the how I was able to fix it for data :
data: {
labels: [{% for year in years %} '{{year}}', {% endfor %}],
datasets: [
{% for site in sites %}
{
label: '{{site.site}}',
yAxisID: 'y',
borderColor: '{{site.color}}',
backgroundColor: 'transparent',
data: [ {% for item in qs %}
{% if item.site == site.site %}
{{item.turn_over}} ,{% endif %} {% endfor %}
]
}, {% endfor %}
]
}

Multiple chart on one page using chart.js and Flask app

I am trying to get multiple charts on one web page with different value. I can get two charts, but displays same data. Can someone please help me what i am missing?
Below is App.py where I am reading data from csv file.
temp.csv
Month,Temperature,Temp
January,7,10
February,7,30
March,10,5
April,15,25
May,20,20
June,23,15
July,26,20
App.py
from flask import Flask, render_template, url_for, redirect, request
import pandas as pd
app = Flask(__name__)
#app.route('/')
def index():
df = pd.read_csv('temp.csv')
legend = 'Monthly Data'
legend1 = "Test"
labels = list(df.Month)
values = list(df.Temperature)
values1 = list(df.Temp)
return render_template('index.html', values=values, labels=labels,
legend=legend,values1=values1, legend1=legend1)
if __name__ == "__main__":
app.run(debug=True)
Below is my index. html. I am trying to call values from App.py file.
index.html
{% extends 'base.html' %}
{%block head %}
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.6.0/Chart.min.js"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<title>My Chart.js Chart</title>
{% endblock %}
{% block body %}
<h1>Burn Page</h1>
<div class="container">
<canvas id="myChart" width="400" height="200"></canvas>
</div>
<div class="container">
<canvas id="myChart2" width="400" height="200"></canvas>
</div>
<script>
Chart.defaults.global.responsive = false;
var chartData = {
labels : [{% for item in labels %}
"{{item}}",
{% endfor %}],
datasets : [{
label: '{{ legend }}',
fill: true,
lineTension: 0.1,
backgroundColor: "rgba(75,192,192,0.4)",
borderColor: "rgba(75,192,192,1)",
borderCapStyle: 'butt',
borderDash: [],
borderDashOffset: 0.0,
borderJoinStyle: 'miter',
pointBorderColor: "rgba(75,192,192,1)",
pointBackgroundColor: "#fff",
pointBorderWidth: 1,
pointHoverRadius: 5,
pointHoverBackgroundColor: "rgba(75,192,192,1)",
pointHoverBorderColor: "rgba(220,220,220,1)",
pointHoverBorderWidth: 2,
pointRadius: 1,
pointHitRadius: 10,
data : [{% for item in values %}
{{item}},
{% endfor %}],
spanGaps: false
}]
}
var ctx = document.getElementById("myChart").getContext("2d");
var myChart = new Chart(ctx, {
type: 'line',
data: chartData,
});
Chart.defaults.global.responsive = false;
var chartData2 = {
labels : [{% for item in labels %}
"{{item}}",
{% endfor %}],
datasets : [{
label: '{{ legend1 }}',
ill: true,
lineTension: 0.1,
backgroundColor: "rgba(75,192,192,0.4)",
borderColor: "rgba(75,192,192,1)",
borderCapStyle: 'butt',
borderDash: [],
borderDashOffset: 0.0,
borderJoinStyle: 'miter',
pointBorderColor: "rgba(75,192,192,1)",
pointBackgroundColor: "#fff",
pointBorderWidth: 1,
pointHoverRadius: 5,
pointHoverBackgroundColor: "rgba(75,192,192,1)",
pointHoverBorderColor: "rgba(220,220,220,1)",
pointHoverBorderWidth: 2,
pointRadius: 1,
pointHitRadius: 10,
data : [{% for item in values1 %}
{{item}},
{% endfor %}],
spanGaps: false
}]
}
var ctx2 = document.getElementById("myChart2").getContext("2d");
var myChart2 = new Chart(ctx2, {
type: 'line',
data: chartData,
});
</script>
{% endblock %}
I finally figured it out. For second chart i was calling first chart function. Changed that and it is all working now.
It should be "chartData2 and not chartData toward the end of my html (java script) code
data: chartData2,
});
</script>
{% endblock %}

Google Chart is not rendering in PDF created by wkhtmltopdf

The google chart images were perfectly coming in PDF till few months back.
But now images are not coming.
If I try the html, google chart is coming correctly.
If I try to convert that HTML into PDF using wkhtmltopdf, chart not showing.
I am using wkhtmltopdf from command line.
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>GRAPH</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
</head>
<body>
<table width="100%">
<tr>
<td align="center">
<b>GRAPH</b>
</td>
</tr>
<tr>
<td align="center">
<div class="text-center" id="chart_div70918" style="display: block; margin: 0 auto; width: 400px;height: 160px; "></div>
</td>
</tr>
</table>
<script type="text/javascript">
var scr = document.createElement("script");
scr.setAttribute("src",'https://www.google.com/jsapi?autoload={"modules":[{"name":"visualization","version":"1","packages":["corechart", "bar"],"callback":"drawChart70918"}]}');
document.head.appendChild(scr);
function drawChart70918() {
var data = google.visualization.arrayToDataTable([
["Subject", "Class Highest", "Marks Obtained", { role: "style" } ]
,["English", 13, 43, "#1909a0"],["Hindi -Oral", 48, 40, "#1909a0"],["Maths", 13, 38, "#1909a0"],["G.k.", 12, 39, "#1909a0"],["Drawing", 48, 44, "#1909a0"] ]);
var view = new google.visualization.DataView(data);
var options = {
fontSize : 6,
fontName: 'Times New Roman',
hAxis :{showTextEvery:1,"slantedText":true, "slantedTextAngle": 45 },
vAxis: {minValue: 0},
legend: { position: "right" },
colors: ['#a5e893', '#1909a0'],
bar: {groupWidth: "40%"},
chartArea:{left:10,top:20,width:'75%',height:'60%'}
};
var chart = new google.visualization.ColumnChart(document.getElementById("chart_div70918"));
chart.draw(view, options);
}
</script>
</body>
</html>

Creating charts using chart.js

I need to create charts using chart.js , however I have created a basic one using the chart.js documentation. But now I want the data source to be HTML Table instead of Array object.
Here is my code:
<!DOCTYPE HTML>
<html>
<head></head>
<body>
<canvas id="c" width="500" height="500"></canvas>
<script src="chart.js"></script>
<script>
var ctx = document.getElementById("c").getContext("2d");
var data = {
labels: ["January", "February", "March", "April", "May", "June", "July"],
datasets: [{
label: "My First dataset",
fillColor: "rgba(220,220,220,0.2)",
strokeColor: "rgba(220,220,220,1)",
pointColor: "rgba(220,220,220,1)",
pointStrokeColor: "#fff",
pointHighlightFill: "#fff",
pointHighlightStroke: "rgba(220,220,220,1)",
data: [65, 59, 80, 81, 56, 55, 40]
}, {
label: "My Second dataset",
fillColor: "rgba(151,187,205,0.2)",
strokeColor: "rgba(151,187,205,1)",
pointColor: "rgba(151,187,205,1)",
pointStrokeColor: "#fff",
pointHighlightFill: "#fff",
pointHighlightStroke: "rgba(151,187,205,1)",
data: [28, 48, 40, 19, 86, 27, 90]
}]
};
var MyNewChart = new Chart(ctx).Line(data);
</script>
<table id="datatable">
<thead>
<tr>
<th></th>
<th>Jane</th>
<th>Jordan</th>
</tr>
</thead>
<tbody>
<tr>
<th>Apples</th>
<td>3</td>
<td>4</td>
</tr>
<tr>
<th>Pears</th>
<td>2</td>
<td>0</td>
</tr>
<tr>
<th>Plums</th>
<td>5</td>
<td>11</td>
</tr>
<tr>
<th>Bananas</th>
<td>1</td>
<td>1</td>
</tr>
<tr>
<th>Oranges</th>
<td>2</td>
<td>4</td>
</tr>
<tr>
<th>Carret</th>
<td>6</td>
<td>4</td>
</tr>
</tbody>
</table>
</body>
</html>
===================
Any help would be appreciated.
Thanks and Regards
This question Looping through table data with jquery has answers that discuss how to pull data from a table using jquery. Ideally if your table is be being generated from server side you could pass that data set into a JSON data set to be used on the page by both chart and table.

Vue.js For loop is not rendering content

I am building a web application using vue.js, vue-resource, vue-mdl and google material design lite.
JS compilation is performed using webpack through laravel elixir.
In this app I have to render a table row for each object from an array returned from a Rest API (Django Rest Framework). I have made the following code inside the html to render content using vue.js:
<tr v-for="customer in customers">
<td class="mdl-data-table__cell--non-numeric">{{ customer.status }}</td>
<td class="mdl-data-table__cell--non-numeric">{{ customer.name }}</td>
<td class="mdl-data-table__cell--non-numeric">{{ customer.company }}</td>
<tr>
This should render all objects in the array as a table row. I have also tried to wrap the above in a template tag like this:
<template v-for="customer in customers">
<tr>
<td class="mdl-data-table__cell--non-numeric">{{ customer.status }}</td>
<td class="mdl-data-table__cell--non-numeric">{{ customer.name }}</td>
<td class="mdl-data-table__cell--non-numeric">{{ customer.company }}</td>
</tr>
</template>
This did not change either.
I have also tried to hardcode the array inside the ready() function of the vue instance, but this did not help either.
window._ = require('lodash');
require('material-design-lite');
window.Vue = require('vue');
require('vue-resource');
var VueMdl = require('vue-mdl');
Vue.use(VueMdl.default);
const app = new Vue({
el:'body',
ready: function(){
//this.getCustomerList();
this.customers = [
{ name: "Peter", status: "true", company: "Company 1"},
{ name: "John", status: "false", company: "Company 2"}
]
},
data: {
customers: [],
response: null,
messages: []
},
methods: {
getCustomerList: function()
{
this.$http({url: '/api/customers/', method: 'GET'}).then(function(response){
//Success
this.customers = response.data
console.log(response.data)
},
function(response){
console.log(response)
})
}
}
})
Changing the above to this does not change either:
window._ = require('lodash');
require('material-design-lite');
window.Vue = require('vue');
require('vue-resource');
var VueMdl = require('vue-mdl');
Vue.use(VueMdl.default);
const app = new Vue({
el:'body',
ready: function(){
//this.getCustomerList();
},
data: {
customers: [
{ name: "Peter", status: "true", company: "Company 1"},
{ name: "John", status: "false", company: "Company 2"}
],
response: null,
messages: []
},
methods: {
getCustomerList: function()
{
this.$http({url: '/api/customers/', method: 'GET'}).then(function(response){
//Success
this.customers = response.data
console.log(response.data)
},
function(response){
console.log(response)
})
}
}
})
I have also tried to just make a plain html table that does not have any of the Google MDL classes applied, and this does also not give any result.
Logging this.customers to the console shows that it does in fact contain the data, but for reason it is not rendering. Why is that? What am I doing wrong?
Here's a snippet of your code, which works as expected. I've added in CDN references to the libraries you mentioned, but I'm not doing anything with them. I offer this as a starting point for you to see if you can find what changes will reproduce your problem here.
const app = new Vue({
el: 'body',
ready: function() {
//this.getCustomerList();
this.customers = [{
name: "Peter",
status: "true",
company: "Company 1"
}, {
name: "John",
status: "false",
company: "Company 2"
}]
},
data: {
customers: [],
response: null,
messages: []
}
})
<script src="//cdnjs.cloudflare.com/ajax/libs/vue/1.0.26/vue.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/vue-resource/0.9.3/vue-resource.min.js"></script>
<link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons">
<link rel="stylesheet" href="https://code.getmdl.io/1.2.0/material.indigo-pink.min.css">
<script defer src="https://code.getmdl.io/1.2.0/material.min.js"></script>
<script src="https://rawgit.com/posva/vue-mdl/develop/dist/vue-mdl.min.js"></script>
<div class="mdl-grid">
<div class="mdl-cell mdl-cell--3-col">
<button id="create-customer" class="mdl-button mdl-js-button mdl-button--raised mdl-js-ripple-effect" #click="$refs.createCustomer.open">
Create customer
</button>
</div>
<div class="mdl-cell mdl-cell--3-col">
<button id="convert-reseller" class="mdl-button mdl-js-button mdl-button--raised mdl-js-ripple-effect">
Convert to reseller
</button>
</div>
<div class="mdl-cell mdl-cell--3-col">
<button id="remove-customer" class="mdl-button mdl-js-button mdl-button--raised mdl-js-ripple-effect">
Remove Customer
</button>
</div>
<div class="mdl-cell mdl-cell--3-col">
<button id="change-status" class="mdl-button mdl-js-button mdl-button--raised mdl-js-ripple-effect">
Change status
</button>
</div>
</div>
<div class="mdl-grid">
<div class="mdl-cell mdl-cell--12-col">
<table class="mdl-data-table mdl-js-data-table mdl-data-table--selectable" style="width:100%;">
<thead>
<tr>
<th class="mdl-data-table__cell--non-numeric">Status</th>
<th class="mdl-data-table__cell--non-numeric">Customer name</th>
<th class="mdl-data-table__cell--non-numeric">Company</th>
</tr>
</thead>
<tbody>
<tr v-for="customer in customers">
<td class="mdl-data-table__cell--non-numeric">{{ customer.status }}</td>
<td class="mdl-data-table__cell--non-numeric">{{ customer.name }}</td>
<td class="mdl-data-table__cell--non-numeric">{{ customer.company }}</td>
</tr>
</tbody>
</table>
</div>
</div>
It seems now to be working.
Inside app.js I had:
const app = new Vue({ el: 'body' })
That, for some reason, conflicted with the one I was creating inside customer_list.js—although my methods worked fine.