Chart loading when changing window size - javascript

I'm creating a chart using chart.js, when I open the web page the chart is there but the data only loads when I resize the window after a few seconds. I assume its something to do with the asynchronous functions but i'm not sure?
Here is my code
let xlabels = [];
let ydata = [];
chartIt();
async function chartIt(){
await getData();
const ctx = document.getElementById('chart').getContext('2d');
const myChart = new Chart(ctx, {
type: 'line',
data: {
labels: xlabels,
datasets:[{
data: ydata
}],
},
options: {
scales: {
yAxes: [{
ticks: {
beginAtZero: true
}
}]
}
}
});
}
async function getData(){
fetch('/test')
.then(function (response) {
return response.json();
})
.then(function (text){
for(var i= 0; i < text.length; ++i){
const date = text[i].date;
xlabels.push(date);
const mass=text[i].mass;
ydata.push(mass);
}
});
}

Related

Javascript not pushing data to the dataArray

Im not a javascript guy but I had some help getting my chart working with chart js here, but since then I had to change the data structure from just 2 tables to 3 (with oneToMany - manyToOne). I feel Im pretty close but can I get some help with pushing the employeeProjectMonths to the dataArray?
The listEmployees looks like this:
var listEmployees = [
{"id":1,"name":"Bill Turner","contractedFrom":"2022-09-01","contractedTo":"2022-10-30",
"employeeProjects":[
{"id":14,"project":{"id":7,"projectNumber":12345,"name":"Project 7","startDate":"2020-01-01","endDate":"2022-12-31","projectLengthInMonths":30.0,"currentBookedMonths":28.0,"remainingBookedMonths":2.0,"numberOfEmployees":5},"employeeBookedMonths":7.7},
{"id":2,"project":{"id":6,"projectNumber":66666,"name":"Project 6","startDate":"2020-10-01","endDate":"2021-12-31","projectLengthInMonths":35.0,"currentBookedMonths":60.0,"remainingBookedMonths":6.0,"numberOfEmployees":6},"employeeBookedMonths":6.0},
{"id":7,"project":{"id":7,"projectNumber":12345,"name":"Project 7","startDate":"2020-01-01","endDate":"2022-12-31","projectLengthInMonths":30.0,"currentBookedMonths":28.0,"remainingBookedMonths":2.0,"numberOfEmployees":5},"employeeBookedMonths":8.0},
{"id":5,"project":{"id":9,"projectNumber":56789,"name":"Project 9","startDate":"2020-10-01","endDate":"2021-12-31","projectLengthInMonths":35.0,"currentBookedMonths":30.0,"remainingBookedMonths":5.0,"numberOfEmployees":3},"employeeBookedMonths":8.0},
{"id":15,"project":{"id":8,"projectNumber":54321,"name":"Project 8","startDate":"2020-05-01","endDate":"2022-06-31","projectLengthInMonths":40.0,"currentBookedMonths":32.0,"remainingBookedMonths":8.0,"numberOfEmployees":4},"employeeBookedMonths":8.8}]},
{"id":2,"name":"Kate Miller","contractedFrom":"2022-01-01","contractedTo":"2022-05-30",
"employeeProjects":[
{"id":3,"project":{"id":4,"projectNumber":44444,"name":"Project 4","startDate":"2020-01-01","endDate":"2022-12-31","projectLengthInMonths":30.0,"currentBookedMonths":40.0,"remainingBookedMonths":4.0,"numberOfEmployees":4},"employeeBookedMonths":14.0},
{"id":6,"project":{"id":7,"projectNumber":12345,"name":"Project 7","startDate":"2020-01-01","endDate":"2022-12-31","projectLengthInMonths":30.0,"currentBookedMonths":28.0,"remainingBookedMonths":2.0,"numberOfEmployees":5},"employeeBookedMonths":5.0},
{"id":8,"project":{"id":9,"projectNumber":56789,"name":"Project 9","startDate":"2020-10-01","endDate":"2021-12-31","projectLengthInMonths":35.0,"currentBookedMonths":30.0,"remainingBookedMonths":5.0,"numberOfEmployees":3},"employeeBookedMonths":5.0},
{"id":13,"project":{"id":8,"projectNumber":54321,"name":"Project 8","startDate":"2020-05-01","endDate":"2022-06-31","projectLengthInMonths":40.0,"currentBookedMonths":32.0,"remainingBookedMonths":8.0,"numberOfEmployees":4},"employeeBookedMonths":6.6}]},
{"id":3,"name":"John Smith","contractedFrom":"2022-06-01","contractedTo":"2022-12-30","employeeProjects":[
{"id":12,"project":{"id":1,"projectNumber":12345,"name":"Project 1","startDate":"2020-01-01","endDate":"2022-12-31","projectLengthInMonths":30.0,"currentBookedMonths":28.0,"remainingBookedMonths":2.0,"numberOfEmployees":5},"employeeBookedMonths":2.5}]}];
and this is the chart
const labels = listEmployees.reduce(function(result, item) {
result.push(item.name);
return result;
}, []);
const randomColorGenerator = function () {
return '#' + (Math.random().toString(16) + '0000000').slice(2, 8);
};
const projects = listEmployees.reduce(function(result, item) {
item.employeeProjects.forEach(function(prj){
const prjId = prj.project.id;
if (!result[prjId]) {
result[prjId] = {
label: prj.project.name,
data: [],
backgroundColor: randomColorGenerator()
};
}
});
return result;
}, {});
listEmployees.forEach(function(item) {
for (const prjId of Object.keys(projects)) {
const prj = projects[prjId];
const empPrj = item.employeeProjects.filter(el => el.project.id === prjId);
if (empPrj.length) {
prj.data.push(empPrj[0].employeeBookedMonths);
} else {
prj.data.push(0);
}
}
});
const ctx = document.getElementById("myChart");
const myChart = new Chart(ctx, {
type: 'bar',
data: {
labels: labels,
datasets: Object.values(projects)
},
options: {
scales: {
x: {
stacked: true
},
y: {
stacked: true
}
}
}
});
The issue is here:
const empPrj = item.employeeProjects.filter(el => el.project.id === prjId);
because you are comparing a string with a number.
Change it in
const empPrj = item.employeeProjects.filter(el => el.project.id === parseFloat(prjId));
and it should work. See snippet.
var listEmployees = [
{"id":1,"name":"Bill Turner","contractedFrom":"2022-09-01","contractedTo":"2022-10-30",
"employeeProjects":[
{"id":14,"project":{"id":7,"projectNumber":12345,"name":"Project 7","startDate":"2020-01-01","endDate":"2022-12-31","projectLengthInMonths":30.0,"currentBookedMonths":28.0,"remainingBookedMonths":2.0,"numberOfEmployees":5},"employeeBookedMonths":7.7},
{"id":2,"project":{"id":6,"projectNumber":66666,"name":"Project 6","startDate":"2020-10-01","endDate":"2021-12-31","projectLengthInMonths":35.0,"currentBookedMonths":60.0,"remainingBookedMonths":6.0,"numberOfEmployees":6},"employeeBookedMonths":6.0},
{"id":7,"project":{"id":7,"projectNumber":12345,"name":"Project 7","startDate":"2020-01-01","endDate":"2022-12-31","projectLengthInMonths":30.0,"currentBookedMonths":28.0,"remainingBookedMonths":2.0,"numberOfEmployees":5},"employeeBookedMonths":8.0},
{"id":5,"project":{"id":9,"projectNumber":56789,"name":"Project 9","startDate":"2020-10-01","endDate":"2021-12-31","projectLengthInMonths":35.0,"currentBookedMonths":30.0,"remainingBookedMonths":5.0,"numberOfEmployees":3},"employeeBookedMonths":8.0},
{"id":15,"project":{"id":8,"projectNumber":54321,"name":"Project 8","startDate":"2020-05-01","endDate":"2022-06-31","projectLengthInMonths":40.0,"currentBookedMonths":32.0,"remainingBookedMonths":8.0,"numberOfEmployees":4},"employeeBookedMonths":8.8}]},
{"id":2,"name":"Kate Miller","contractedFrom":"2022-01-01","contractedTo":"2022-05-30",
"employeeProjects":[
{"id":3,"project":{"id":4,"projectNumber":44444,"name":"Project 4","startDate":"2020-01-01","endDate":"2022-12-31","projectLengthInMonths":30.0,"currentBookedMonths":40.0,"remainingBookedMonths":4.0,"numberOfEmployees":4},"employeeBookedMonths":14.0},
{"id":6,"project":{"id":7,"projectNumber":12345,"name":"Project 7","startDate":"2020-01-01","endDate":"2022-12-31","projectLengthInMonths":30.0,"currentBookedMonths":28.0,"remainingBookedMonths":2.0,"numberOfEmployees":5},"employeeBookedMonths":5.0},
{"id":8,"project":{"id":9,"projectNumber":56789,"name":"Project 9","startDate":"2020-10-01","endDate":"2021-12-31","projectLengthInMonths":35.0,"currentBookedMonths":30.0,"remainingBookedMonths":5.0,"numberOfEmployees":3},"employeeBookedMonths":5.0},
{"id":13,"project":{"id":8,"projectNumber":54321,"name":"Project 8","startDate":"2020-05-01","endDate":"2022-06-31","projectLengthInMonths":40.0,"currentBookedMonths":32.0,"remainingBookedMonths":8.0,"numberOfEmployees":4},"employeeBookedMonths":6.6}]},
{"id":3,"name":"John Smith","contractedFrom":"2022-06-01","contractedTo":"2022-12-30","employeeProjects":[
{"id":12,"project":{"id":1,"projectNumber":12345,"name":"Project 1","startDate":"2020-01-01","endDate":"2022-12-31","projectLengthInMonths":30.0,"currentBookedMonths":28.0,"remainingBookedMonths":2.0,"numberOfEmployees":5},"employeeBookedMonths":2.5}]}];
const labels = listEmployees.reduce(function(result, item) {
result.push(item.name);
return result;
}, []);
const randomColorGenerator = function () {
return '#' + (Math.random().toString(16) + '0000000').slice(2, 8);
};
const projects = listEmployees.reduce(function(result, item) {
item.employeeProjects.forEach(function(prj){
const prjId = prj.project.id;
if (!result[prjId]) {
result[prjId] = {
label: prj.project.name,
data: [],
backgroundColor: randomColorGenerator()
};
}
});
return result;
}, {});
listEmployees.forEach(function(item) {
for (const prjId of Object.keys(projects)) {
const prj = projects[prjId];
const empPrj = item.employeeProjects.filter(el => el.project.id === parseFloat(prjId));
if (empPrj.length) {
prj.data.push(empPrj[0].employeeBookedMonths);
} else {
prj.data.push(0);
}
}
});
const ctx = document.getElementById("myChart");
const myChart = new Chart(ctx, {
type: 'bar',
data: {
labels: labels,
datasets: Object.values(projects)
},
options: {
scales: {
x: {
stacked: true
},
y: {
stacked: true
}
}
}
});
.myChartDiv {
max-width: 600px;
max-height: 400px;
backgroundColor: green;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.9.1/chart.min.js"></script>
<html>
<body>
<div class="myChartDiv">
<canvas id="myChart" width="600" height="400"></canvas>
</div>
</body>
</html>

Frontend and backend for chart using chartjs, mongodb, and controller

I am new to generating a chart using the ajax mechanism and chartjs. It seems that I managed to generate the graph but they are plotted incorrectly. Please enlighten me on how I could improve. Would really appreciate Thank you
Following is my code in javascript to plot chart
var ctx = document.getElementById('myChart').getContext('2d');
$.ajax({
url:"/dashboard",
type:"POST",
data: {},
error: function() {
alert("Error");
},
success: function(data, status, xhr) {
debugger
// declare all variables to draw chart
var chartDim = {};
var chartDim = data.chartDim;
var xLabels = data.labels;
var vLabels = [];
var vData = [];
let newValues =[]
// get from database to push to draw the chart
for (const [key, values] of Object.entries(chartDim)) {
vLabels.push(key);
let newValues = values.map(myFunction);
debugger;
vData.push(newValues);
}
debugger
var myChart = new Chart(ctx, {
data: {
labels: xLabels,
datasets: []
},
options: {
responsive: false
}
});
// draw to chart
debugger
for (i= 0; i < vLabels.length; i++ ) {
myChart.data.datasets.push({
label: vLabels[i],
type: "bar",
// borderColor: '#'+(0x1ff0000+Math.random()*0xffffff).toString(16).substr(1,6),
borderColor: '#'+(0x1100000+Math.random()*0xffffff).toString(16).substr(1,6),
backgroundColor: "rgba(249, 238, 236, 0.74)",
data: vData[i],
spanGaps: true
});
myChart.update();
}
}})
This happens because while making your chart you push each data point as a new dataset. Instead you just need to use a single dataset and pass the data array to it like so:
var myChart = new Chart(ctx, {
type: 'bar',
data: {
labels: xLabels,
datasets: [{
borderColor: '#' + (0x1100000 + Math.random() * 0xffffff).toString(16).substr(1, 6),
backgroundColor: "rgba(249, 238, 236, 0.74)",
data: vData,
spanGaps: true
}]
},
options: {
responsive: false
}
});

How can I show extra data in chart.js tooltip?

I'm trying to show weight_id retrieved from mysql data in a chart.js tooltip (shown as (weight_ids[index]) in the image). And later, I intend to show a modal instead of a tooltip to let users update or delete that data. I presume I cannot achieve that without linking the linechart's point data with id stored in mysql. How can I incorporate this id data?
I would appreciate any help very much.
enter image description here
My code is as follows:
<canvas id="myChart"></canvas>
<script src="https://cdn.jsdelivr.net/npm/chart.js#2.9.4/dist/Chart.min.js"></script>
{{-- グラフを描画--}}
<script>
//ラベル
const labels = #json($date_labels);
// id
const weight_ids = #json($weight_ids);
//体重ログ
const weight_logs = #json($weight_logs);
const aryMax = function(a, b) {
return Math.max(a, b);
};
const aryMin = function(a, b) {
return Math.min(a, b);
};
let min_label = Math.floor((weight_logs).reduce(aryMin) - 0.5);
let max_label = Math.ceil((weight_logs).reduce(aryMax) + 0.5);
console.log(weight_ids);
console.log(weight_logs);
console.log(min_label, max_label);
//グラフを描画
var ctx = document.getElementById("myChart");
var myChart = new Chart(ctx, {
type: 'line',
data : {
labels: labels, // x軸ラベル
datasets: [
{
label: `Weight (weight_ids[index])`,
data: weight_logs,
tension: 0,
borderColor: "rgba(37,78,255,1)",
backgroundColor: "rgba(0,0,0,0)",
pointRadius: 3
}
]
},
options: {
title: {
display: false,
text: ''
},
legend: {
display: false,
},
scales: {
yAxes: [
{
ticks: {
min: min_label, // ラベル最小値
max: max_label, // ラベル最大値
},
scaleLabel: {
display: true,
fontSize: 16,
labelString: '体重 (kg)'
}
}
],
},
hover: {
mode: 'point'
},
onClick: function clickHandler(evt) {
var firstPoint = myChart.getElementAtEvent(evt)[0];
if (firstPoint) {
var label = myChart.data.labels[firstPoint._index];
var value = myChart.data.datasets[firstPoint._datasetIndex].data[firstPoint._index];
console.log(label);
console.log(value);
if (value) {
$('#weidhtModal').modal('show');
}
}
}
}
});
</script>
Thank you!
I found a way to retrieve weight_id using the following function.
onClick: function clickHandler(evt, activeElements) {
if (activeElements.length) {
var element = this.getElementAtEvent(evt);
var index = element[0]._index;
var _datasetIndex = element[0]._datasetIndex;
var weightId = weight_ids[index];
var weightLog = weight_logs[index];
console.log(index);
console.log(weightId);
console.log(this.data.labels[index]);
console.log(weightLog);
}
}

How to display different datasets from different ajax calls in the same ChartJS?

I'm trying to display different datasets, from different ajax calls, in the same chartJS.
The idea is to show different stats per month, on 13 consecutive months.
1 ajax call = 1 stat for each of the 13 months.
The JSON data for on stat looks like this :
[{"month":"June 2020","value":0},{"month":"May 2020","value":0},{"month":"April 2020","value":0},{"month":"March 2020","value":0},{"month":"February 2020","value":30},{"month":"January 2020","value":182},{"month":"December 2019","value":143},{"month":"November 2019","value":111},{"month":"October 2019","value":103},{"month":"September 2019","value":128},{"month":"August 2019","value":71},{"month":"July 2019","value":129},{"month":"June 2019","value":98}]
Of course, the values determinate the bars, and the months are the chart's labels.
I can display one stat for every month, but I can't add the others (3 more stats to show).
The expected result : 4 bars for each month.
Here is my working code for one dataset :
function getJsonDataForStat1() {
return $.ajax
({
url: 'getJsonDataForStat1',
type: 'get'
});
}
function setChart() {
$.when(getJsonDataForStat1()).done(function (stats) {
stats = JSON.parse(stats);
var data = [], labels = [];
stats.forEach(function (s) {
labels.push(s.month);
data.push(s.value);
});
var ctx = document.getElementById('graph').getContext('2d');
var graph = new Chart(ctx, {
type: 'bar',
data: {
labels: labels,
datasets: [
{
label: 'stat 1',
data: data,
backgroundColor: '#735288',
borderColor: '#3c8dbc',
borderWidth: 1
}],
options: {
scales: {
yAxes: [{
ticks: {
beginAtZero: true
}
}]
}
}
}
});
});
}
How to add the 3 others ?
Any help would be appreciated.
Thanks a lot !
Let's suppose you fetched your data and have multiple statistics/arrays containing the data for each month.
You can compute a lookup that maps the month to the values of the different statistics.
The labels are simply the keys, although you'd probably want to sort them based on the date. The datasets can easily be computed by mapping the labels.
var lkp = [stat1, stat2].flat().reduce((acc, cur) => {
const {
month,
value
} = cur;
acc[month] = acc[month] || [];
acc[month].push(value);
return acc;
}, {});
//{'June 2020': [0, 10], ...}
var labels = Object.keys(lkp).sort((a, b) => (Date.parse(a) % (1000 * 60 * 60 * 24 * 365)) - (Date.parse(b) % (1000 * 60 * 60 * 24 * 365)))
// ['June 2020', 'May 2020']
var colors = ['red', 'green'];
var datasets = [0, 1].map((index) => {
const data = labels.map(label => lkp[label][index]);
return {
data,
label: `Statistic ${index}`,
backgroundColor: colors[index],
}
});
var options = {
type: 'bar',
data: {
labels,
datasets,
},
options: {
scales: {
yAxes: [{
ticks: {
reverse: false
}
}]
}
}
}
var ctx = document.getElementById('chart').getContext('2d');
try {
new Chart(ctx, options);
} catch (e) {
//catch co error
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.3.0/Chart.js"></script>
<script>
var stat1 = [{"month":"June 2020","value":0},{"month":"May 2020","value":0},{"month":"April 2020","value":0},{"month":"March 2020","value":0},{"month":"February 2020","value":30},{"month":"January 2020","value":182},{"month":"December 2019","value":143},{"month":"November 2019","value":111},{"month":"October 2019","value":103},{"month":"September 2019","value":128},{"month":"August 2019","value":71},{"month":"July 2019","value":129},{"month":"June 2019","value":98}]
var stat2 = [{"month":"June 2020","value":10},{"month":"May 2020","value":25},{"month":"April 2020","value":75},{"month":"March 2020","value":80},{"month":"February 2020","value":30},{"month":"January 2020","value":182},{"month":"December 2019","value":23},{"month":"November 2019","value":123},{"month":"October 2019","value":50},{"month":"September 2019","value":128},{"month":"August 2019","value":71},{"month":"July 2019","value":129},{"month":"June 2019","value":98}];
</script>
<canvas id="chart" width="600" height="400"></canvas>
I have finally succeeded, based on Martin M.'s idea.
Here is my code (maybe it can help someone who has the same issue).
It works perfectly.
var graph = setChart();
updateChart();
function setChart() {
$.when(getData1()).done(function (stats) {
stats = JSON.parse(stats);
var data = [], labels = [];
stats.forEach(function (s) {
labels.push(s.month);
data.push(s.value);
});
var ctx = document.getElementById('graph').getContext('2d');
return graph = new Chart(ctx, {
type: 'bar',
data: {
labels: labels,
datasets: [
{
label: 'data 1',
data: data,
backgroundColor: '#00c0ef',
}],
options: {
scales: {
yAxes: [{
ticks: {
beginAtZero: true
}
}]
}
}
}
});
});
}
function updateChart() {
$.when(setChart()).done(function () {
// I've repeated the following block for data 3 and 4 (still inside updateChart())
$.when(getData2()).done(function (stats) {
stats = JSON.parse(stats);
var data = [];
stats.forEach(function (s) {
data.push(s.value);
});
var dataset = {};
dataset.label = "data 2";
dataset.backgroundColor = '#061834';
dataset.data = data;
graph.data.datasets.push(dataset);
graph.update();
})
})
}
Thank you all for your help !

Using JSON in Chart.js with Angular.js

I'm having next problem -> when i use the encode json string printed by a php echo tag in my front-end everything works, but when i want to use it with the angular get function I don't get it to work.
Codeigniter Controller (back-end)
public function getLogs(){
$this->load->model('Home_model');
$logs = $this->Home_model->getLogs();
echo json_encode($logs);
}
AngularJs Controller (front-end)
$http.get('index.php/Welcome/getLogs')
.then(function (response) {
json = response.data;
});
var chartjsData = [];
for (var i = 0; i < json.length; i++) {
chartjsData.push(json[i].aantal);
}
var chartjsLabels = [];
for (var i = 0; i < json.length; i++) {
chartjsLabels.push(json[i].datum);
}
var ctx = document.getElementById('myChart').getContext('2d');
var myChart = new Chart(ctx, {
type: 'line',
data: {
labels: chartjsLabels,
datasets: [{
label: "Aantal meldingen",
borderColor: 'rgb(255, 131, 48)',
data: chartjsData,
fill: false
}]
},
options: {
responsive: false
}
});
Thanks in advance!
Since, the $http.get() method is asynchronous, you need to initialize your chart inside the callback function of $http.get() , like so ...
$http.get('index.php/Welcome/getLogs')
.then(function(response) {
json = response.data;
json = JSON.parse(json); //parse JSON string (if needed)
var chartjsData = [];
for (var i = 0; i < json.length; i++) {
chartjsData.push(json[i].aantal);
}
var chartjsLabels = [];
for (var i = 0; i < json.length; i++) {
chartjsLabels.push(json[i].datum);
}
var ctx = document.getElementById('myChart').getContext('2d');
var myChart = new Chart(ctx, {
type: 'line',
data: {
labels: chartjsLabels,
datasets: [{
label: "Aantal meldingen",
borderColor: 'rgb(255, 131, 48)',
data: chartjsData,
fill: false
}]
},
options: {
responsive: false
}
});
});

Categories

Resources