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
}
});
Related
I just learned to make a web And I want to know how to make chart js to display values in real time. Can you guys advise or tell me how to do it for me?
var data = [];
var temp = [];
async function getRandomUser() {
const response = await fetch('http://localhost:1111/chartpie');
const data = await response.json();
addData(data);
}
function addData(object) {
temp.push(object.temperature);
var z = 80;
var y = z - temp;
var ctx = document.getElementById("myPieChart");
myPieChart = new Chart(ctx, {
type: "doughnut",
data: {
labels: ["Temperature", "Null"],
datasets: [{
data: [temp, y],
backgroundColor: [
"orange",
"rgba(0, 172, 105, 1)"
],
}]
},
options: {
legend: {
display: false
},
}
});
}
getRandomUser()
The values I retrieved are the values retrieved from mongoDB, fetched in the form of an array. Thank You!
You can just update the chart in "real time" by adding to the charts data array.
see: https://www.chartjs.org/docs/latest/developers/updates.html
Adding and removing data is supported by changing the data array. To
add data, just add data into the data array as seen in this example.
function addData(chart, label, data) {
chart.data.labels.push(label);
chart.data.datasets.forEach((dataset) => {
dataset.data.push(data);
});
chart.update();
}
For example...
const canvas = document.getElementById('myChart');
canvas.height = 75;
const labels = [
'dju32',
'ad6b2',
'0f23f',
'asd4c',
];
const data = {
labels: labels,
datasets: [{
label: 'Test',
backgroundColor: 'rgb(255, 99, 132)',
borderColor: 'rgb(255, 99, 132)',
data: [0, 10, 5, 4],
}]
};
const config = {
type: 'line',
data: data,
options: {}
};
const myChart = new Chart(
canvas,
config
);
// function to update the chart
function addData(chart, label, data) {
chart.data.labels.push(label);
chart.data.datasets.forEach((dataset) => {
dataset.data.push(data);
});
chart.update();
}
// randomly add new data
setInterval(function() {
const newLabel = (Math.random() + 1).toString(36).substring(7);
const newData = Math.floor(Math.random() * (10 - 1 + 1)) + 1;
addData(myChart, newLabel, newData);
}, 1000);
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<div>
<canvas id="myChart"></canvas>
</div>
I am using Chart.js to draw a simple line chart. Everything looks fine, I get data from API but I can't able to show on the line chart :
$.ajax({
url: "https://api.thevirustracker.com/free-api?countryTimeline=PK",
dataType: 'json',
success: function(result) {
const datachart = []
console.log("datachart", datachart)
for (var i = 0, l = result.timelineitems.length; i < l; i++) {
const entries = result.timelineitems[i]
const x = Object.keys(entries);
const y = Object.values(entries)
// const y = [2,2,4,7,5,4,7,4,1,0,7,4,8,5,44,1,44,111,44,1,11,1,77,88,55,22,99,66,55,77,44,55,22,00,44,77,8,9,5,7,4,1]
datachart.push({
y: y,
x: x
})
}
var ctx = document.getElementById('myChart').getContext('2d');
var chart = new Chart(ctx, {
// The type of chart we want to create
type: 'line',
// The data for our dataset
data: {
datasets: [{
data: datachart,
label: ["datachart[1]"],
borderColor: "#18bc9c",
fill: false
}]
},
// Configuration options go here
options: {}
});
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.3/Chart.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<canvas id="myChart" width="200" height="200"></canvas>
I want to add an array of x variable as a label and data is to add Object.values(entries).new_daily_cases as a data to be shown
The data property of individual datasets for a line chart can be passed in two formats, number[] or Point[]. Point[] is useful in the following cases:
If the number of data points from individual datasets is different.
if x-values of data points from different datasets are different.
In your case, if you specify data.labels, there's no need to define the data of individual datasets as an array of Point.
Please have a look at your amended code below:
$.ajax({
url: "https://api.thevirustracker.com/free-api?countryTimeline=PK",
dataType: 'json',
success: result => {
const rawData = result.timelineitems[0];
delete rawData.stat;
const labels = Object.keys(rawData);
const data = Object.values(rawData);
var chart = new Chart(document.getElementById('myChart'), {
type: 'line',
data: {
labels: labels,
datasets: [{
label: 'New Daily Cases',
data: data.map(o => o.new_daily_cases),
borderColor: "violet",
fill: false
},
{
label: 'New Daily Deaths',
data: data.map(o => o.new_daily_deaths),
borderColor: "orange",
fill: false
},
{
label: 'Total Cases',
data: data.map(o => o.total_cases),
borderColor: "blue",
fill: false
},
{
label: 'Total recoveries',
data: data.map(o => o.total_recoveries),
borderColor: "green",
fill: false
},
{
label: 'Total Deaths',
data: data.map(o => o.total_deaths),
borderColor: "red",
fill: false
}]
},
options: {}
});
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.3/Chart.bundle.min.js"></script>
<canvas id="myChart" height="90"></canvas>
My chart doesn't read my array data unless I hit breakpoints while obtaining the data through JSON url. If I am debugging, my chart renders okay, if not, it's blank. Please help. Thank you!
<script>
var labels = [];
var payments = [];
jQuery.getJSON("<?=base_url()?>Admin/getJSONWeeklyDates", function(data) {
labels = data;
});
jQuery.getJSON("<?=base_url()?>Admin/getJSONWeeklyPayments", function(data) {
payments = data;
});
</script>
<script>
( function ( $ ) {
"use strict";
// single bar chart
var ctx = document.getElementById( "singelBarChart" );
ctx.height = 150;
var myChart = new Chart( ctx, {
type: 'bar',
data: {
labels: labels,
datasets: [
{
label: "Payments",
data: payments,
borderColor: "rgba(0, 123, 255, 0.9)",
borderWidth: "0",
backgroundColor: "rgba(0, 123, 255, 0.5)"
}
]
},
options: {
scales: {
yAxes: [ {
ticks: {
beginAtZero: true
}
} ]
}
}
} );
} )( jQuery );
</script>
Note: When I console log the labels' and payments' array length it shows 0 even though it has 2 values when I access the array through console after page load.
Following is my javascript Code, but the only thing really relevant is the last function. I want to update the Chart to add another dataset, without reloading the Page. But for reason the added dataset is always undefined. The commented-out line, which uses the exact same array of data, on the other hand works. Since I'm new to javascript I'm not sure, if I missed something obvious, or if chart.js just doesn't support this kind of thing at all.
const CHART = document.getElementById("lineChart");
var dts1 = [
{
label: "Abfall gesamt",
data: Abfall_gesamt,
}
];
var dts2 = [
{
label: "Abfall schadstoffhaltiger",
data: Abfall_schadstoff,
}
];
var lineChart = new Chart(CHART, {
type: 'line',
data: {
labels: Jahr,
datasets: dts1
}
});
function myFunction(){
//lineChart.data.datasets[0].data = Abfall_schadstoff;
lineChart.data.datasets.push(dts2);
lineChart.update();
}
The issue is, you are defining your datasets (dts1 and dts2) as an array. They should be an object, like so ...
var dts1 = {
label: "Abfall gesamt",
data: Abfall_gesamt,
};
var dts2 = {
label: "Abfall schadstoffhaltiger",
data: Abfall_schadstoff,
};
and then, when generating the chart, set datasets value as ...
datasets: [dts1]
ᴅᴇᴍᴏ
const CHART = document.getElementById("lineChart");
var Abfall_gesamt = [1, 2, 3];
var Abfall_schadstoff = [4, 5, 6]
var dts1 = {
label: "Abfall gesamt",
data: Abfall_gesamt,
backgroundColor: 'rgba(255, 0, 0, 0.2)'
};
var dts2 = {
label: "Abfall schadstoffhaltiger",
data: Abfall_schadstoff,
backgroundColor: 'rgba(0, 0, 255, 0.2)'
};
var lineChart = new Chart(CHART, {
type: 'line',
data: {
labels: ['Jahr', 'Mahr', 'Kadr'],
datasets: [dts1]
},
options: {
responsive: false,
scales: {
yAxes: [{
ticks: {
beginAtZero: true,
stepSize: 1
}
}]
}
}
});
function myFunction() {
//lineChart.data.datasets[0].data = Abfall_schadstoff;
lineChart.data.datasets.push(dts2);
lineChart.update();
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.5.0/Chart.min.js"></script>
<button id="add" onclick="myFunction()">Add Dataset</button>
<canvas id="lineChart" height="190"></canvas>
I'm quite new with JS, and have a problem with Chart.js and multiple charts.
I load all libraries like jquery and chart.js from CDNs
Then I have one plugins.js for localy loaded plugins
And one js called main.js with all the custom JS.
I get this error:
Uncaught TypeError: Cannot read property 'style' of undefined
My question is:
How do I keep all my Chart.js charts in one .js file, that get loaded on all website pages, but not all pages contains all charts.
(I have a site that consists on multiple pages with different charts, and I'm thinking it's smarter to load all at once in one JS-file)
Appreciate any other pointers also. :)
-
About the code
I've posted the code below and also created a JSFiddle: https://jsfiddle.net/NoLooseEnds/1pt3m41a/
In the main.js I have all my Chart.js data like so (among other things):
// *************************************
// Chart.js
// *************************************
// Global Settings
Chart.defaults.global.defaultFontColor = "rgba(43,43,43,1)";
Chart.defaults.global.defaultFontFamily = "'ApexNew-Medium', 'Helvetica Neue', 'Helvetica', 'Arial', sans-serif";
Chart.defaults.global.defaultFontSize = 12;
Chart.defaults.global.defaultFontStyle = "normal";
Chart.defaults.global.maintainAspectRatio = false;
// Disable click on legend
Chart.defaults.global.legend.onClick = (e) => e.stopPropagation();
// Bar Charts settings
var barChart__options = {
};
// Doughnut settings
var dnutChart__options = {
legend: {
position: "bottom",
// Disable click on legend
onClick: (e) => e.stopPropagation()
}
};
// *************************************
// Datasets
// *************************************
// Bar Chart X
var barChartX__data = {
labels: ["Alpha", "Bravo", "Charlie"],
datasets: [
{
label: "2015",
borderWidth: 0,
backgroundColor: "rgba(43,43,43,1)",
data: [410,430,110]
},
{
label: "2016",
borderWidth: 0,
backgroundColor: "rgba(233,131,0,1.0)",
data: [405,360,150]
}
]
};
const barChartX = $("#barChartX");
let ChartX = new Chart(barChartX, {
type: "bar",
data: barChartX__data,
options: barChart__options
});
// Doughnut Chart Y
var dnutChartY__data = {
labels: ["Alpha", "Bravo"],
datasets: [
{
label: "Points",
borderWidth: 0,
backgroundColor: ["rgba(43,43,43,1)", "rgba(233,131,0,1.0)"],
data: [90,270]
}
]
};
const dnutChartY = $("#dnutChartY");
let ChartY = new Chart(dnutChartY, {
type: "doughnut",
data: dnutChartY__data,
options: dnutChart__options
});
// Doughnut Chart Z
var dnutChartZ__data = {
labels: ["Alpha", "Bravo", "Charlie"],
datasets: [
{
label: "Points",
borderWidth: 0,
backgroundColor: ["rgba(233,131,0,1.0)","rgba(239,162,64,1.0)","rgba(244,193,127,1.0)"],
data: [405,360,150]
}
]
};
const dnutChartZ = $("#dnutChartZ");
let ChartZ = new Chart(dnutChartZ, {
type: "doughnut",
data: dnutChartZ__data,
options: dnutChart__options
});
And my HTML like so:
<div class="example__chart">
<div>
<canvas id="barChartX" height="400" width="400"></canvas>
</div>
<!--
<div>
<canvas id="dnutChartY" height="400" width="400"></canvas>
</div>
-->
<div>
<canvas id="dnutChartZ" height="400" width="400"></canvas>
</div>
</div>
As you can see I have commented out a part to trigger the error.
You can create a helper function and check whenever the DOM element exists for the barChartX, dnutChartY, dnutChartZ or any other DOM element like this:
var doChart = function(o, d) {
if (typeof(o) != 'undefined' && o.length > 0) {
return new Chart(o, d);
} else {
return null;
}
}
Then your Chart.js code will be like this
// *************************************
// Chart.js
// *************************************
// Global Settings
Chart.defaults.global.defaultFontColor = "rgba(43,43,43,1)";
Chart.defaults.global.defaultFontFamily = "'ApexNew-Medium', 'Helvetica Neue', 'Helvetica', 'Arial', sans-serif";
Chart.defaults.global.defaultFontSize = 12;
Chart.defaults.global.defaultFontStyle = "normal";
Chart.defaults.global.maintainAspectRatio = false;
// Disable click on legend
Chart.defaults.global.legend.onClick = (e) => e.stopPropagation();
var doChart = function(o, d) {
if (typeof(o) != 'undefined' && o.length > 0) {
return new Chart(o, d);
} else {
return null;
}
}
// Bar Charts settings
var barChart__options = {};
// Doughnut settings
var dnutChart__options = {
legend: {
position: "bottom",
// Disable click on legend
onClick: (e) => e.stopPropagation()
}
};
// *************************************
// Datasets
// *************************************
// Bar Chart X
var barChartX__data = {
labels: ["Alpha", "Bravo", "Charlie"],
datasets: [{
label: "2015",
borderWidth: 0,
backgroundColor: "rgba(43,43,43,1)",
data: [410, 430, 110]
},
{
label: "2016",
borderWidth: 0,
backgroundColor: "rgba(233,131,0,1.0)",
data: [405, 360, 150]
}
]
};
const barChartX = $("#barChartX");
/*let ChartX = new Chart(barChartX, {
type: "bar",
data: barChartX__data,
options: barChart__options
});*/
let ChartX = doChart(barChartX, {
type: "bar",
data: barChartX__data,
options: barChart__options
});
// Doughnut Chart Y
var dnutChartY__data = {
labels: ["Alpha", "Bravo"],
datasets: [{
label: "Points",
borderWidth: 0,
backgroundColor: ["rgba(43,43,43,1)", "rgba(233,131,0,1.0)"],
data: [90, 270]
}]
};
const dnutChartY = $("#dnutChartY");
let ChartY = doChart(dnutChartY, {
type: "doughnut",
data: dnutChartY__data,
options: dnutChart__options
});
// Doughnut Chart Z
var dnutChartZ__data = {
labels: ["Alpha", "Bravo", "Charlie"],
datasets: [{
label: "Points",
borderWidth: 0,
backgroundColor: ["rgba(233,131,0,1.0)", "rgba(239,162,64,1.0)", "rgba(244,193,127,1.0)"],
data: [405, 360, 150]
}]
};
const dnutChartZ = $("#dnutChartZ");
let ChartZ = doChart(dnutChartZ, {
type: "doughnut",
data: dnutChartZ__data,
options: dnutChart__options
});
Please check my working example with no javascript errors here: http://zikro.gr/dbg/html/chartsjs/
UPDATE
Please have a look at the JSFiddle example here: https://jsfiddle.net/h1dafqjx/2/
UPDATE 2
Problem analysis and solution
The problem you are facing, is that you want to have multiple declarations and chart setups in one javascript file that you are going to use on many location which may happen some of these locations do not have some of the declared elements, thus you want your code to handle those cases.
You declare a chart like this:
const barChartX = $("#barChartX");
let ChartX = new Chart(barChartX, {
type: "bar",
data: barChartX__data,
options: barChart__options
});
In order to handle a missing DOM element, like when the $("#barChartX") does not exists, you need to create a condition to check those cases.
For excample:
const barChartX = $("#barChartX");
if(typeof(barChartX) != 'undefined' && barChartX.length > 0) {
let ChartX = new Chart(barChartX, {
type: "bar",
data: barChartX__data,
options: barChart__options
});
}
With the obove code, you check if the barChartX is defined and if it actually contains any elements with the barChartX.length > 0 condition.
Now, in order to do not repeat things, we keep it simple and do all that checking in a function. Thus we create the function doChart like this:
var doChart = function(o, d) {
if (typeof(o) != 'undefined' && o.length > 0) {
return new Chart(o, d);
} else {
return null;
}
}
The first parameter o is the DOM element we want to check and the second parameter d is the chart object properties.
For example:
let ChartX = doChart(barChartX, {
type: "bar",
data: barChartX__data,
options: barChart__options
});
Here we pass to the doChart function the barChartX jQuery object of the element in order for the function to check if exists. Then we pass the chart object parameters by the second parameter named d, which is the chart object properties for creating the new chart:
{
type: "bar",
data: barChartX__data,
options: barChart__options
}