Connecting API data array to chartjs in django - javascript

I am trying to create a chart using chartjs and this chart is displaying API data(Stock Data). I have made the API successfully and make the data wanted in the form of an array inorder to put it in the chart. When I define the API data array as a variable and use the variable in the chart data it doesn't display anything:
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<script src="https://cdn.jsdelivr.net/npm/chartjs-adapter-date-fns/dist/chartjs-adapter-date-fns.bundle.min.js"></script>
<script>
const ctx = document.getElementById('myChart');
let y=new Array();
let theapi = fetch('api_src')
.then(response => response.json())
.then(data => {
const thewanted = Object.values(data)[1]
for (const [key, value] of Object.entries(thewanted)) {
y.push(key);
}
console.log(y)
})
new Chart(ctx, {
type: 'line',
data: {
labels: y,
datasets: [{
label: '# of Votes',
data: [12, 19, 3, 5, 2, 3],
borderWidth: 1
}]
}
,
options: {
scales: {
y: {
beginAtZero: true
}}}});
</script>
if you look at the labels in the chart you will find that I have used the variable as the value of the labels but it doesn't work and whan I console.log the variable I find that it contains the values that I want.
Note: When I closed the pc and opened it again after time I found that it worked but when I refreshed the page or restarted the server it doesn't work
update: the chart data is shown only when I zoom the page in or out and other than that it shows a blank chart.

Related

ChartJs Doughnut parsing datasets

I‘m trying to create a doughnut chart with custom objects as data. I don’t know if it is a bug or am I stupid. 😩
If the type of the chart is „bar“ everything is working as expected but if I change it to doughnut the chart area is empty.
Here is the code for the bar chart:
var myChart = new Chart(ctx, {
type: 'bar',
data: {
datasets: [{
label: '# of Votes',
data: [{vX:12, n:'vx'}, {vX:13, n:'vx2'}],
parsing:{
yAxisKey:'vX',
xAxisKey: 'n'
},
borderWidth: 1
}]
},
options: {
}
});
and that‘s my doughnut:
var myChart = new Chart(ctx, {
type: 'doughnut',
data: {
datasets: [{
label: '# of Votes',
data: [{vX:12, n:'vx'}, {vX:13, n:'vx2'}],
parsing:{
yAxisKey:'vX',
},
borderWidth: 1
}]
},
options: {
}
});
Is parsing not supported for doughnut charts? I can‘t find information about this in the docs.
thanks, Christian
Regarding data structures, the Chart.js documentation says:
For a pie (and doughnut) chart, datasets need to contain an array of data points. The data points should be a number (...)
Therefore, parsing doesn't make sense and is probably not supported. The problem can be solved by mapping your data to labels and data as follows.
var data = [{vX:12, n:'vx'}, {vX:13, n:'vx2'}];
new Chart('myChart', {
type: 'doughnut',
data: {
labels: data.map(v => v.n),
datasets: [{
label: '# of Votes',
data: data.map(v => v.vX),
borderWidth: 1
}]
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.5.1/chart.min.js"></script>
<canvas id="myChart"></canvas>
At the moment chart.js does not support object notation with parsing for pie/doughnut charts.
There has been a pr for this a few days ago which is merged into the master so as soon as a new version of chart.js releases, anything beyond version 3.5.1 will have this change in it and then you can use your object.
Otherwise you can take the route #uminder suggested and map the data yourself
As mentioned by Christian, It's available since 3.6.0 (2021-10-24, see https://github.com/chartjs/Chart.js/issues/9440) with sth. like this:
options: {
parsing: {
key: "the-label-key',
}
}
ref official doc: https://www.chartjs.org/docs/latest/general/data-structures.html

Passing data to a chart javascript object and array

What is the best approach to display the data in a chart?
To begin, my application has an empty array that receives objects.
// location where the users are storage
let usersList = [];
// these are the information from an user
const newUser = {
name:`${user.name.first} ${user.name.last}`,
social: Math.floor(Math.random() * 1000 )
}
So, by the end of my code, I have the chart, everything is working but with dummy data.
const myChart = new Chart(ctx, {
type: 'line',
data: {
labels: ['Red', 'Blue', 'Yellow', 'Green', 'Purple', 'Orange'], // should get the usersList.name
datasets: [{
label: ' Views per channel ',
data: [12, 10, 3, 5, 2, 3], // // should get the usersList.social
borderWidth: 1
}]
},
options: {
scales: {
yAxes: [{
ticks: {
beginAtZero: true
}
}]
}
}
});
Ideally, I would need to change the labels to have the name of each user, and the data to have the social of each user. My initial thought was a for loop, but I remember that ES6 has array destructuring.
I am not sure how to approach the problem, do you have any insight?
Thank you very much.
You can use the Array.map() method on the usersList to create the arrays that contain the desired attributes of the users.
Your code would have to be changed as follows:
data: {
labels: usersList.map(u => u.name),
datasets: [{
label: ' Views per channel ',
data: usersList.map(u => u.social),
borderWidth: 1
}]
}

How to draw 2d line time plot with chart.js

I want to draw line chart with chart.js but all example show single array as data I have 2d data. X is day (date object) and y is price of the product.
I have function like this that create data:
function format(data) {
const result = [];
Object.entries(data).forEach(([key, value]) => {
var data = {
label: key,
backgroundColor: 'rgba(0,0,0,0)',
data: value.map(data => ({y: data[0], x: new Date(data[1])}))
};
result.push(data);
});
return result;
}
from documentation I see that I can use object with {x,y} but this render only 2 points.
the data output look like this:
[
{
"label": "cyfrowe.pl",
"backgroundColor": "rgba(0,0,0,0)",
"data": [
{
"y": 9299,
"x": "2020-08-01T05:19:28.000Z"
},
{
"y": 9299,
"x": "2020-08-02T04:15:01.000Z"
},
my code for chart look like this:
var canvas = document.querySelector('canvas');
var ctx = canvas.getContext('2d');
console.log(ctx);
fetch('price.json')
.then(res => res.json())
.then(data => {
data = format(data);
console.log(data);
console.log(JSON.stringify(data.slice(0,1), true, 4));
var myLineChart = new Chart(ctx, {
type: 'line',
data:{ datasets: data }
});
});
In fact The time should be in days since I have prices for each date at about same hour.
Here is my demo that is not working. (the demo was updated with the answer code).
To make your code work, you could use a scatter chart and add the options showLine: true to each dataset.
In order to obtain formatted labels for each day, you need to define the x-axis as a time cartesian axis by adding the following configuration to chart options.
scales: {
xAxes: [{
type: 'time',
time: {
unit: 'day',
tooltipFormat: 'MMM DD'
}
}]
}
Please note that Chart.js internally uses Moment.js for the functionality of the time axis. Therefore you should use the bundled version of Chart.js that includes Moment.js in a single file.
When it comes to also show the labels in the tooltip, add the following to the chart options.
tooltips: {
mode: 'point',
callbacks: {
title: (tooltipItem, data) => data.datasets[tooltipItem[0].datasetIndex].label
}
}
Please take a look at your amended CodePen.

Move x-axis to pass through given y-axis value in chart.js

I have the following chart:
let ctx = document.getElementById("chart").getContext("2d");
var datasets = [
{
data: [1.1, 0.8, 1.2, 1.1, 0.7],
type: "line",
},
];
var options = {};
var data = {labels: [1, 2, 3, 4, 5], datasets: datasets};
var config = {type: "line", data: data, options: options};
var chart = new Chart(ctx, config);
which when renders shows the x-axis starting on a y-axis value of 0.6. Is there a way to have the x-axis running through a y-axis value of 1?
Not sure whether I understand your problem well. In case you want to your y-axis value start with 1 instead of 0.6 there is way to tell Chart.js by passing some options about these values.
Modifying your options definition like this:
var options = {
scales: {
yAxes: [{
ticks: {
min: 1
}
}]
}
};
should do the tick!
Check out the related documentation where you can find some more options and examples how to use them ;)

ChartJS – How to show border on empty pie chart?

I have a couple of pie/doughnut charts displayed using ChartJS. Usually, they contain data like [200, 1200, 300] and [30, 500] to give an estimate, but at rare occasions, they will contain [0, 0, 0] and [0, 0]. The problem then, is that the chart disappears, even though I have a border enabled. I have solved this by adding dummy values to the first element in the arrays, but I don't like how the code looks and want a better way.
Is it possible to make the border visible (a circle) when the array contains only zeroes?
Edit:
I don't seem to get any answers to this question. Is it considered a bug when the border is not showing on empty data or is this intended behavior? I don't know if anyone else has had this problem. I still need to find an elegant way to deal with this issue, and I haven't found one yet.
This is not a bug, as the borders are rendered per data item. If all the data is 0s, then every slice has no width, so no border can show (the only other way to handle this scenario for ChartJS would be to give each item equal sizing, which isn't better).
You can add a dummy value without a label and filter the legend and tooltips so that the data is treated like a blank space to the user. In the example below, a check before rendering the chart ensures that if all data points are 0, a data point with a value of 1 is added to the chart with no label. Two datasets are shown to highlight the difference.
let ctx = document.getElementById('chartContainer').getContext('2d');
let data = [[0, 0, 0], [1,2,3]];
let labels = ["A", "B", "C"];
let bgColors = ['yellow', 'orange', 'aquamarine'];
let options = {
borderWidth: 1,
borderColor: 'black',
legend: {
labels: {
// Prevent items with undefined labels from appearing in the legend
filter: (item) => item.text !== undefined
}
},
tooltips: {
// Prevent items with undefined labels from showing tooltips
filter: (item, chart) => chart.labels[item.index] !== undefined
}
}
let chartConfig = {
type: 'pie',
data: {
labels: labels,
datasets: [{
data: data[0],
backgroundColor: bgColors,
label: "data",
borderColor: 'black',
borderWidth: 2
}, {
data: data[1],
backgroundColor: bgColors,
label: "data",
borderColor: 'black',
borderWidth: 2
}]
},
options: options
}
// Check if data is all 0s; if it is, add dummy data to end with empty label
chartConfig.data.datasets.forEach(dataset => {
if (dataset.data.every(el => el === 0)) {
dataset.backgroundColor.push('rgba(255,255,255,0)');
dataset.data.push(1);
}
})
let pieChart = new Chart(ctx, chartConfig);
.chartContainer {
height: 200px;
width: 200px;
}
<script src="https://cdn.jsdelivr.net/npm/chart.js#2.8.0/dist/Chart.min.js"></script>
<div class="chartContainer">
<canvas id="chartContainer" width="200" height="200"></canvas>
</div>

Categories