Iterating through array in Chart.js data field - javascript

Update:
var voltagedata1 = [];
batterybank1.forEach(function(element){
var voltage = {x: element.timestamp, y:element.voltage};
voltagedata1.push(voltage);
})
data: voltagedata1
I have an array which I want to iterate through in the data field of the Chart.js chart.
This code works for example:
data: [
{x: '2019-08-12 09:40:15', y:4}, {x: '2019-08-13 09:40:15', y:5}, {x: '2019-08-14 09:40:15', y:6},
],
Then trying to iterate through the array as follows:
batterybank1.forEach(function(element){
console.log(element)
"{x:\'element.timestamp', y:element.voltage},"
})
The console.log(element) gives a correct output, however the chart is not getting updated... on the console I am getting no warnings/errors - just the graph does not output.
The following does not work either, only the console.log is outputted but the graph is not updated.
batterybank1.forEach(function(element){
console.log(element)
"{x:\'2019-08-12 09:40:15', 1},"
})

It's explained in the documentation, that you add your points to the chart one at a time, like so:
batterybank1.forEach(function(element){
chart.data.datasets[0].data.push(element);
})
This is assuming that element is in the same format as the points in data.
After that you need to call chart.update(); to show the new data.
below is a working example:
let data = [{t: '2019-08-12 09:40:15', y:4}, {t: '2019-08-13 09:40:15', y:5}, {t: '2019-08-14 09:40:15', y:6}, {t: '2019-08-15 09:40:15', y:7}];
var chart = new Chart(document.getElementById('cht'), { type:'bar', data:
{
datasets:[{
label: 'CHRT - Chart.js Corporation',
backgroundColor: '#ff0000',
borderColor: '#ff0000',
type: 'bar',
pointRadius: 0,
fill: false,
lineTension: 0,
borderWidth: 2,
data: data}]
}, options:{
scales: {
xAxes: [
{
type: 'time',
distribution: 'series',
ticks:
{
source: 'data',
autoSkip: true
}
}]
}
} });
document.getElementById('addPoints').addEventListener('click', function() {
let extra = [{t: '2019-08-16 09:40:15', y:4}, {t: '2019-08-17 09:40:15', y:5}, {t: '2019-08-18 09:40:15', y:6}, {t: '2019-08-19 09:40:15', y:7}];
extra.forEach(p =>
{
chart.data.datasets[0].data.push(p);
});
chart.update();
});
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.8.0/Chart.min.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.8.0/Chart.bundle.js"></script>
<button id="addPoints">Add Points</button>
<canvas id="cht" class="chartjs" width="770" height="385" style="display: block; width: 770px; height: 385px;">

Related

multiple line charts with independent data Javascript (Chart.js or google-vizualisation)

js and I have two datasets:
data1 = [[0,1],[2,3],[5,7]] and data2 = [[1,4],[2,6],[5,2],[7,1]] for example.
Each data list contains lists that represent points to plot on a same chart. (x and y values)
I want to plot exactely like this :
https://www.chartjs.org/samples/latest/charts/line/multi-axis.html
But as you can see, my data lists don't have the same x or y values and they don't even have the same size, so I can't use the regular:
data: {labels = [1,2,3,4,5],
data = [7,8,3,1,2],
data = [9,1,2,3,4]} //for example
How can I code this chart only with javascript (no jQuery please) ? I didn't find anything on the Internet that might help.
Any suggestions would matter to me !
You can use a scatter chart, that accepts the data as an array of objects containing x and y properties. To turn it into a line chart, define showLine: true inside the data configuration objects.
Given your data structures, the following line of code produces the data structure expected by Chart.js.
data1.map(o => ({ x: o[0], y: o[1] }))
Please have a look at below runnable code snippet.
const data1 = [[0,1],[2,3],[5,7]];
const data2 = [[1,4],[2,6],[5,2],[7,1]];
new Chart('line-chart', {
type: "scatter",
responsive: true,
data: {
datasets: [
{
data: data1.map(o => ({ x: o[0], y: o[1] })),
label: 'Dataset 1',
showLine: true,
fill: false,
borderColor: 'red'
},
{
data: data2.map(o => ({ x: o[0], y: o[1] })),
label: 'Dataset 2',
showLine: true,
fill: false,
borderColor: 'blue'
}
]
},
options: {
scales: {
yAxes: [{
ticks: {
beginAtZero: true
}
}]
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.3/Chart.min.js"></script>
<canvas id="line-chart" height="80"></canvas>

chart.js plotting timeseries

Attempting to pass through data from django to a webpage to render a responsive chart. The data are being passed correctly to js, but I am driving myself crazy trying to understand why charts.js is throwing an error.
I have hardcoded some data for example:
function setLineChart() {
var ctx = document.getElementById("myLineChart").getContext('2d');
var dat_1 = {
label: 'things',
borderColor: 'blue',
data: [
{t: new Date("04/01/2020"), y: 310},
{t: new Date("04/02/2020"), y: 315},
{t: new Date("04/03/2020"), y: 320},
]
};
var myLineChart = new Chart(ctx, {
type: 'line',
data: {
datasets: [dat_1]
},
options: {
scales: {
xAxes: [{
type: 'time',
time: {
unit: 'day'
},
}],
yAxes: [{
ticks: {
beginAtZero: true
}
}]
}
}
})
}
<canvas id="myLineChart" width="600" height="600"></canvas>
And this returns a Uncaught TypeError: Cannot read property 'skip' of undefined error that I can't debug. setLineChart() gets called as part of an ajax response on a form update. When I comment out the options section, it does render a chart, but misses off the last data point, and has undefined as the x-axis marker.
Any help would be appreciated.
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.
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.3/Chart.bundle.min.js"></script>
This will solve your problem as the following amended code snippet illustrates.
var ctx = document.getElementById("myLineChart").getContext('2d');
var dat_1 = {
label: 'things',
borderColor: 'blue',
data: [
{ t: new Date("04/01/2020"), y: 310 },
{ t: new Date("04/02/2020"), y: 315 },
{ t: new Date("04/03/2020"), y: 320 },
]
};
var myLineChart = new Chart(ctx, {
type: 'line',
data: {
datasets: [dat_1]
},
options: {
scales: {
xAxes: [{
type: 'time',
time: {
unit: 'day'
},
}],
yAxes: [{
ticks: {
beginAtZero: true
}
}]
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.3/Chart.bundle.min.js"></script>
<canvas id="myLineChart" height="90"></canvas>

How can I express this element?

Hello I have this code using javascript and chart.js :
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.5.0/Chart.min.js"></script>
<link rel="stylesheet" href="style.css" />
</head>
<body>
<div id = "Global">
<div id = "gauche">
<canvas id="line-chart" width="800" height="450"></canvas>
<script>
var ctx = document.getElementById("line-chart").getContext('2d');
var config = {
type: 'line',
data: {
datasets: [{
data: [{'y': 426777.148122,'x': 18.123},
{'y': 258927.721326,'x': 46.8603108462},
{'y': 5419.37148146,'x': 1110.14081215},
{'y': 5136.33830766,'x': 1138.878123}],
label: "Model",
borderColor: "#3e95cd",
fill: false
}, {
label : 'Data',
fill:false,
showLine: false,
backgroundColor: "#FF0000",
data : [{x: 17.0, y: 454995.091169},
{x: 1137.0, y: 3369.7047454},
{x: 1138.0, y: 3539.605825},
{x: 1140.0, y: 4927.1313084}],
type: 'line'
}]
},
options: {
title:{
display: true,
text:"Graph"
},
scales: {
xAxes: [{
type: 'logarithmic',
position: 'bottom'
}],
yAxes: [{
type: 'logarithmic'
}]
}
}
};
var forecast_chart = new Chart(ctx, config);
alert(data.datasets[0].data);
</script>
But when I type this : alert(data.datasets[0].data); I get nothing... basically I just want to express this 426777.148122 which is part of the data but I don't know how to do it, I thought to write this data.datasets[0].data but it does not work...
Any ideas ?
Thank you very much !
Try:
alert(JSON.stringify(config.data.datasets[0].data[0]));
You will need JSON.stringify because config.data.datasets[0].data is also an array of objects
or
alert(config.data.datasets[0].data[0].x);
To get the X value of the first entry of config.data.datasets[0].data

How to show bar labels in legend in Chart.js 2.1.6?

I'm creating charts using Chart.js and I want to show the labels for the bars in the legend, not the title of the dataset (there is only one), please see the below image as an example:
My current legend just looks like this:
I have looked through the docs but to no avail, I found them very confusing actually.
Here is my current code:
var chart_0 = new Chart($('#cp_chart_0'), {
type: 'bar'
, data: {
labels: ['Blue','Green','Yellow','Red','Purple','Orange']
, datasets: [{
label: 'Dataset 1'
, borderWidth: 0
, backgroundColor: ['#2C79C5','#7FA830','#7B57C3','#ED4D40','#EC802F','#1DC6D3']
, data: ['12','2','5','0','9','1']
}]
}
});
Thanks!
In one of the most recent releases of Chart.js 2.1.x, they added back this functionality. So go get the latest release first. Then insert the code below.
It is located under the options and legend. Here is how you use it:
options: {
legend: {
position: 'right'
}
}
Easiest way is to provide your data with multiple sets :
data: {
labels: ['total votes']
, datasets: [{
label: 'Blue'
, backgroundColor: ['#2C79C5']
, data: ['12']
},{
label: 'Green'
, backgroundColor: ['#7FA830']
, data: ['2']
},
...
]
}
But you can generate a custom labels using generateLabels - http://www.chartjs.org/docs/#chart-configuration-legend-configuration
Or even customise the whole legend, including formatting, with legendCallback - http://www.chartjs.org/docs/#chart-configuration-common-chart-configuration
This solution uses Chart.js version 3. You can pre-process your data using the Plugin Core API. The API offers different hooks that may be used for executing custom code.
I use the beforeInit hook to create individual datasets for each defined label/value pair. Note that the data of these new datasets are defined in point format (for instance [{ x: 1, y: 12 }]):
beforeInit: chart => {
let dataset = chart.config.data.datasets[0];
chart.config.data.datasets = chart.config.data.labels.map((l, i) => ({
label: l,
data: [{ x: i + 1, y: dataset.data[i] }],
backgroundColor: dataset.backgroundColor[i],
categoryPercentage: 1
}));
chart.config.data.labels = undefined;
}
Further you need to define a second x-axis that will contain the labels.
x1: {
offset: true,
gridLines: {
display: false
}
}
The labels on x1 need to be collected and defined programmatically each time the hidden state of a dataset changes. This can be done in the beforeLayout hook.
beforeLayout: chart => chart.options.scales.x1.labels = chart.config.data.datasets.filter((ds, i) => !chart.getDatasetMeta(i).hidden).map(ds => ds.label)
Please take a look at below runnable code and see how it works.
new Chart('chart', {
type: 'bar',
plugins: [{
beforeInit: chart => {
let dataset = chart.config.data.datasets[0];
chart.config.data.datasets = chart.config.data.labels.map((l, i) => ({
label: l,
data: [{ x: i + 1, y: dataset.data[i] }],
backgroundColor: dataset.backgroundColor[i],
categoryPercentage: 1
}));
chart.config.data.labels = undefined;
},
beforeLayout: chart => chart.options.scales.x1.labels = chart.config.data.datasets.filter((ds, i) => !chart.getDatasetMeta(i).hidden).map(ds => ds.label)
}],
data: {
labels: ['Blue', 'Green', 'Yellow', 'Red', 'Purple', 'Orange'],
datasets: [{
data: ['12', '2', '5', '0', '9', '1'],
backgroundColor: ['#2C79C5', '#7FA830', '#FFF200', '#ED4D40', '#800080', '#EC802F']
}]
},
options: {
interaction: {
intersect: true,
mode: 'nearest'
},
plugins: {
legend: {
position: 'right'
},
tooltip: {
callbacks: {
title: () => undefined
}
}
},
scales: {
y: {
beginAtZero: true
},
x: {
display: false
},
x1: {
offset: true,
gridLines: {
display: false
}
}
}
}
});
canvas {
max-width: 400px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.2.0/chart.min.js"></script>
<canvas id="chart" height="120"></canvas>

Morris Chart is Missing Half Part

I used morris chart in my application project to show some details about quantity of sales.
After executing the AJAX request, the chart is only showing half part. Here's the syntax:
var chartBahan = Morris.Bar ({
element: 'morris-analytics-bahan',
xkey: '2',
ykeys: ['3'],
labels: ['Quantity Bahan'],
resize: false,
gridEnabled: true
});
//getting the morris chart over bahan and karakteristik
function getBahanPotensial(kode){
//ajax call
$.ajax({
type:"POST",
async: false,
url:"<%= request.getContextPath()%>/GenerateListBahanPotensial",
data:{
kode:kode
},
success: function(data){
chartBahan.setData($.parseJSON(data));
chartBahan.redraw();
},
error:function(msg){
alert("Data Failed to Analyze" + msg);
}
});
}
var chartKarakter = new Morris.Bar ({
element: 'morris-analytics-karakter',
xkey: '2',
ykeys: ['3'],
labels: ['Karakter Quantity'],
resize: true
});
function getKarakterPotensial(kode){
//ajax call
$.ajax({
type:"POST",
async: false,
url:"<%= request.getContextPath()%>/GenerateListKarakterPotensial",
data:{
kode:kode
},
success:function(data){
chartKarakter.setData($.parseJSON(data));
chartKarakter.redraw();
},
error:function(msg){
alert("Data Failed to Analyze" + msg);
}
});
}
I execute the above function from another function let say doProcess()
function sendRequest(thecode){
if(thecode === ""){ alert("Tolong Input Kode Produk");}
else {
var kodebarang = thecode;
}
//executing AJAX call.
$.ajax({
type:"POST",
async: false,
url:"<%= request.getContextPath()%>/GenerateAnalytics",
data:{
kodebarang:kodebarang
},
success:function(msg){
$('#result_analysis').show();
$('#navigation_button').show();
new Morris.Bar ({
element: 'morris-analytics-bar',
data: $.parseJSON(msg),
xkey: '1',
ykeys: ['2', '3'],
labels: ['Sales Area', 'Tingkat Penjualan'],
barRatio: 0.4,
xLabelAngle: 0,
hideHover: 'auto'
});
//execute the morris chart others !! PENTING
var kodeb = $('#bahan_id').val();
var kodek = $('#karakteristik_id').val();
getBahanPotensial(kodeb);
getKarakterPotensial(kodek);
},
error:function(msg){
alert("Data Failed to Analyze" + msg);
}
});
}
but the problem is, when i create Morris Chart in Success Callback
success:function(msg){
$('#result_analysis').show();
$('#navigation_button').show();
new Morris.Bar ({
element: 'morris-analytics-bar',
data: $.parseJSON(msg),
xkey: '1',
ykeys: ['2', '3'],
labels: ['Sales Area', 'Tingkat Penjualan'],
barRatio: 0.4,
xLabelAngle: 0,
hideHover: 'auto'
});
The chart is properly showing. Here's the screen shot:
But the other chart when i use template for charting (outside the success callback) the chart is BROKEN
here's the screenshot
then, i have dropdown list to regenerate the chart based on specific parameter, the chart is properly showing (all data show) BUT the chart is only half PAGE. here's the screenshot:
Is there any ideas what going on?
UPDATE
What I mean template is code like this:
var chartBahan = Morris.Bar ({
element: 'morris-analytics-bahan',
xkey: '2',
ykeys: ['3'],
labels: ['Quantity Bahan'],
resize: false,
gridEnabled: true
});
and the method to call the template is
success:function(data){
chartBahan.setData($.parseJSON(data));
chartBahan.redraw();
},
The RIGHT chart is the FIRST Screenshot. It's wider than the other two.
UPDATED 2
still getting error on charts created by Morris :(
here's the screenshot.
I solved that issue by setting the width of the svg element to 100% in css
svg{
width: 100% !important
}
Two last charts from your example threw lots of errors in the console of Google Chrome (you can open it by pressing F12).
The reason is that the data property is required when you call Morris.Bar({ data: ... }), but in you example you didn't have this property. So you should completely remove your declarations like var chartBahan = Morris.Bar (... and replace the success callback with this code:
function getBahanPotensial(kode){
$.ajax({
...
success: function(data){
if (window.chartBahan) {
chartBahan.setData($.parseJSON(data));
// chartBahan.redraw(); // useless call, it can be removed
} else {
window.chartBahan = Morris.Bar ({
element: 'morris-analytics-bahan',
data: $.parseJSON(data),
xkey: '2',
ykeys: ['3'],
labels: ['Quantity Bahan'],
resize: false,
gridEnabled: true
});
}
}
...
});
}
In my code I check whether the global variable window.chartBahan exists and if it doesn't - I create a new chart; otherwise I call setData and the chart updates itself automatically.
Also you haven't posted your HTML mark-up, it may have issues as well. I used this HTML code and it worked fine:
<body>
<div id="morris-analytics-bar" style="height: 250px;"></div>
<div id="morris-analytics-bahan" style="height: 250px;"></div>
<div id="morris-analytics-karakter" style="height: 250px;"></div>
</body>
//Java script code
Morris.Line({
element: 'hero-area',
data: getdata("<?php echo base_url('user/getYearlPremiumuser');?>") ,
xkey: 'Year',
parseTime: false,
ykeys: ['Teacher', 'Student'],
labels: ['Teacher', 'Student'],
hideHover: 'false',
lineWidth: 1,
pointSize: 5,
lineColors: ['#4a8bc2', '#ff6c60'],
fillOpacity:7,
smooth: true
});
********//php code ( code codeigniter)********
public function getYearlPremiumuser()
{
$teacherArray={ y: '2014', a: 50, b: 90},
{ y: '2015', a: 65, b: 75},
{ y: '2016', a: 50, b: 50},
{ y: '2017', a: 75, b: 60},
{ y: '2018', a: 80, b: 65},
{ y: '2019', a: 90, b: 70},
{ y: '2020', a: 100, b: 75},
{ y: '2021', a: 115, b: 75},
{ y: '2022', a: 120, b: 85},
{ y: '2023', a: 145, b: 85},
{ y: '2024', a: 160, b: 95}
for($i=0;$i<count($teacherArray);$i++)
{
$temp=array();
$temp= array_merge($teacherArray[$i],$studentarray[$i]);
$finalResultArray[]=$temp;
}
echo json_encode($finalResultArray);
}
click here to know more
I have similar issue using Morris.js and Angular2 - the problem in my case was that I use in DIV with chart the *ngIf='showChart' (or [hidden]='!showChart') - and when I set up chart, the showChar=false so the div doesn't exist. In my case I read date periodic in every 1min so at first dataLoad i see nothing, after second dataLoad i see half/part of chart). So I fix this by (typescript):
showchart = true;
setTimeout( () => { this.setUpChart() }, 1 );
And it works :)

Categories

Resources