Chart.js update function (chart,labels,data) will not update the chart - javascript

I cannot debug the following code. I would like to update chart data (not add on top; delete current data and add completely new dataset). (Not)Working example on codepen:
https://codepen.io/anon/pen/bvBxpr
var config = {
type: 'line',
data: {
labels: ["January", "February", "March", "April", "May", "June", "July"],
datasets: [{
label: "My First dataset",
data: [65, 0, 80, 81, 56, 85, 40],
fill: false
}]
}
};
var ctx = document.getElementById("myChart").getContext("2d");
var myChart = new Chart(ctx, config);
labelsNew = ["Why", "u", "no", "work", "???"];
dataNew = [2, 4, 5, 6, 10];
function updateData(chart, label, data) {
removeData();
chart.data.labels.push(label);
chart.data.datasets.forEach((dataset) => {
dataset.data.push(data);
});
chart.update();
};
function removeData(chart) {
chart.data.labels.pop();
chart.data.datasets.forEach((dataset) => {
dataset.data.pop();
});
chart.update();
}
$('.button-container').on('click', 'button', updateData(myChart, labelsNew, dataNew));

I figured it out. This works:
function addData(chart, label, data) {
chart.data.labels = label
chart.data.datasets.forEach((dataset) => {
dataset.data = data;
});
chart.update();
}
$("#btn").click(function() {
addData (myChart, labelsNew, dataNew);
});
instead of pushing the data (which adds on), data needs to be allocated by " = ".

I see 2 problems:
in function updateData() missing chart argument to removeData(chart);
click handler for button, use simply:
$("#btn").click(function() {
updateData(myChart, labelsNew, dataNew)
});

var config = {
type: 'line',
data: {
labels: ["January", "February", "March", "April", "May", "June", "July"],
datasets: [{
label: "My First dataset",
data: [65, 0, 80, 81, 56, 85, 40],
fill: false
}]
}
};
var ctx = document.getElementById("myChart").getContext("2d");
var myChart = new Chart(ctx, config);
labelsNew = ["Why", "u", "no", "work", "???"];
dataNew = [2, 4, 5, 6, 10];
function addData(chart, label, data) {
chart.data.labels = label
chart.data.datasets.forEach((dataset) => {
dataset.data = data;
});
chart.update();
}
function clickupdate(){
addData(myChart, labelsNew, dataNew);
}
.chart-container {
height: 300px;
width: 500px;
position: relative;
}
canvas {
position: absolute;
}
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<div class="button-container">
<button onclick="clickupdate()">Change Data</button>
</div>
<div class="chart-container">
<canvas id="myChart"></canvas>
</div>

Related

How to add on click event to chart js

Hello I have a question concerning js charts. I have already created one in django application and i want to generate a javascript alert by clicking a certain point in the chart.
How can the alert get the value of the point that i choose?
For example with the value 92 like what is shown in the figure below:
This can be done with an onClick even handler as follows:
onClick: (event, elements, chart) => {
if (elements[0]) {
const i = elements[0].index;
alert(chart.data.labels[i] + ': ' + chart.data.datasets[0].data[i]);
}
}
Please take a look at below runnable code and see how it works.
new Chart('myChart', {
type: 'line',
data: {
labels: ["January", "February", "March", "April", "May", "June", "July"],
datasets: [{
label: '# of Votes',
data: [65, 59, 80, 81, 56, 55, 40],
borderColor: '#a00'
}]
},
options: {
onClick: (event, elements, chart) => {
if (elements[0]) {
const i = elements[0].index;
alert(chart.data.labels[i] + ': ' + chart.data.datasets[0].data[i]);
}
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.7.1/chart.min.js"></script>
<canvas id="myChart" width="400" height="95"></canvas>

How to access all data in a function with ChartJs?

Consider the following code.
var chartData = {
labels: ["January", "February", "March", "April", "May", "June"],
datasets: [{
fillColor: "#79D1CF",
strokeColor: "#79D1CF",
data: [60, 80, 81, 56, 55, 40]
}]
};
var ctx = document.getElementById("myChart1").getContext("2d");
var myLine = new Chart(ctx, {
type: "line",
data: chartData,
showTooltips: false,
onAnimationComplete: function() {
var ctx = this.chart.ctx;
ctx.font = this.scale.font;
ctx.fillStyle = this.scale.textColor
ctx.textAlign = "center";
ctx.textBaseline = "bottom";
this.datasets.forEach(function(dataset) {
dataset.points.forEach(function(points) {
ctx.fillText(points.value, points.x, points.y - 10);
});
})
}
});
<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/3.6.2/chart.min.js"></script>
<canvas id="myChart1" height="300" width="500"></canvas>
Because I use the function in the onAnimationComplete in different graphs, I like to create a JavaScript file where I collect all the functions and use them. For example
var chart = new Chart(ctx, eval(config));
chart.options.animation.onComplete = function () {
window["AnimationComplete1"](chart);
}
function AnimationComplete1(chart) {
var ctx = chart.ctx;
ctx.textAlign = "center";
ctx.textBaseline = "bottom";
chart.data.datasets.forEach(function (dataset) {
dataset.points.forEach(function (points) {
ctx.fillText(points.value, points.x, points.y - 10);
});
})
}
In this code, the problem is that in the function I don't have access to the point from the dataset from chart.data.datasets. Also, I don't have access to the scale for font and textColor.
Is there a way to access those values from a common function?
The Chart.js animation onComplete callback function must be defined inside the chart options.
options: {
animation: {
onComplete: ctx => {
// do your stuff
}
}
}
Please take a look at your amended code below and see how it works.
var chartData = {
labels: ["January", "February", "March", "April", "May", "June"],
datasets: [{
fillColor: "#79D1CF",
strokeColor: "#79D1CF",
data: [60, 80, 81, 56, 55, 40]
}]
};
new Chart('myChart1', {
type: "line",
data: chartData,
options: {
animation: {
onComplete: ctx => {
console.log(ctx.chart.data.datasets);
console.log(ctx.chart.options.scales.x);
}
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.8.0/chart.min.js"></script>
<canvas id="myChart1" height="300" width="500"></canvas>

chart.js Is there way to color line chart ticks depending on value

I have simple chart.js line chart:
I need to color lines between ticks, depending on previous value like that:
If next value is lower than prev line must be red, if higher color is green.
Any ideas how to achieve this?
You can check the following solution.
var ctx = document.getElementById('myChart').getContext('2d');
//adding custom chart type
Chart.defaults.multicolorLine = Chart.defaults.line;
Chart.controllers.multicolorLine = Chart.controllers.line.extend({
draw: function(ease) {
var
startIndex = 0,
meta = this.getMeta(),
points = meta.data || [],
colors = this.getDataset().colors,
area = this.chart.chartArea,
originalDatasets = meta.dataset._children
.filter(function(data) {
return !isNaN(data._view.y);
});
function _setColor(newColor, meta) {
meta.dataset._view.borderColor = newColor;
}
if (!colors) {
Chart.controllers.line.prototype.draw.call(this, ease);
return;
}
for (var i = 2; i <= colors.length; i++) {
if (colors[i-1] !== colors[i]) {
_setColor(colors[i-1], meta);
meta.dataset._children = originalDatasets.slice(startIndex, i);
meta.dataset.draw();
startIndex = i - 1;
}
}
meta.dataset._children = originalDatasets.slice(startIndex);
meta.dataset.draw();
meta.dataset._children = originalDatasets;
points.forEach(function(point) {
point.draw(area);
});
}
});
// build colors sequence
const data = [0, 10, 5, 2, 20, 30, 45];
const availableColors = ['red', 'green'];
let colors = [];
data.forEach(item => {
availableColors.forEach(color => {
colors.push(color)
})
})
var chart = new Chart(ctx, {
// The type of chart we want to create
type: 'multicolorLine',
// The data for our dataset
data: {
labels: ["January", "February", "March", "April", "May", "June", "July"],
datasets: [{
label: "My First dataset",
borderColor: 'rgb(255, 99, 132)',
data: data,
//first color is not important
colors: ['', ...colors]
}]
},
// Configuration options go here
options: {}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.1/Chart.bundle.min.js"></script>
<canvas id="myChart"></canvas>

.datasets is undefined when trying to access bars from chart.js

I'm trying to recreate this example:
chart.js bar chart color change based on value
With the following code
<script src="/chart.js/dist/Chart.js"></script>
<canvas id="myChart" width="400" height="400"></canvas>
<script>
var ctx = document.getElementById('myChart').getContext('2d');
window.myChart = new Chart(ctx, {
type: 'bar',
data: {
labels: ['Red', 'Blue', 'Yellow', 'Green', 'Purple', 'Orange'],
datasets: [{
label: '# of Votes',
data: [12, 19, 3, 5, 3, 3],
fillColor: "rgba(220,220,220,0.5)",
strokeColor: "rgba(220,220,220,0.8)",
highlightFill: "rgba(220,220,220,0.75)",
highlightStroke: "rgba(220,220,220,1)",
borderWidth: 1
}]
},
});
var bars = myChart.datasets[0].bars;
for (i = 0; i < bars.length; i++) {
var color = "green";
//You can check for bars[i].value and put your conditions here
if (bars[i].value < 3) {
color = "red";
} else if (bars[i].value < 5) {
color = "orange"
} else if (bars[i].value < 8) {
color = "yellow"
} else {
color = "green"
}
bars[i].fillColor = color;
}
myChart.update();
</script>
but I get in console the TypeError:
myChart.datasets is undefined on the line var bars = myChart.datasets[0].bars;
Do you have an idea what I'm overlooking?
Thank you
Here is the complete example you want.
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.8.0/Chart.min.js"></script>
<canvas id="myChart" width="400" height="400"></canvas>
<script>
//Creating a barchart with default values
var myChart = new Chart(document.getElementById("myChart"), {
"type": "bar",
"data": {
"labels": ["January", "February", "March", "April", "May", "June", "July"],
"datasets": [{
"label": "My First Dataset",
"data": [65, 59, 80, 81, 56, 55, 40],
"fill": false,
"backgroundColor": ["#fb4d4d", "#fb9d4d", "#f8fb4d", "#98fb4d", "#4effee", "#4cb9f8", "#574cf8"],
"borderColor": ["#fb4d4d", "#fb9d4d", "#f8fb4d", "#98fb4d", "#4effee", "#4cb9f8", "#574cf8"],
"borderWidth": 1
}]
},
"options": {
"scales": {
"yAxes": [{
"ticks": {
"beginAtZero": true
}
}]
}
}
});
//Getting the bar-chart existing values
var bars = myChart.config.data.datasets[0];
var data = bars.data;
//Updating the existing value (object which holds value)
for (i = 0; i < data.length; i++) {
var bgcolor = "";
var brcolor = "";
if (data[i] < 30) {
bgcolor = "red";
brcolor = "red";
} else if (data[i] < 50) {
bgcolor = "orange";
brcolor = "orange";
} else if (data[i] < 80) {
bgcolor = "yellow";
brcolor = "yellow";
} else {
bgcolor = "green";
brcolor = "green";
}
bars.backgroundColor[i] = bgcolor;
bars.borderColor[i] = brcolor;
}
//Triggering the chart update in 3 seconds.
setTimeout(function(){
myChart.update();
}, 3000);
</script>
your dataset was empty, was not being done as the example quoted
The correct way to do as the example you mentioned is:
var barChartData = {
labels: ['Red', 'Blue', 'Yellow', 'Green', 'Purple', 'Orange'],
datasets: [
{
label: '# of Votes',
data: [12, 19, 3, 5, 3, 3],
fillColor: "rgba(220,220,220,0.5)",
strokeColor: "rgba(220,220,220,0.8)",
highlightFill: "rgba(220,220,220,0.75)",
highlightStroke: "rgba(220,220,220,1)",
borderWidth: 1
}
]
};
var ctx = document.getElementById('myChart').getContext('2d');
window.myObjBar = new Chart(ctx).Bar(barChartData, {
responsive : true
});
var bars = myObjBar.datasets[0].bars;
for(i=0;i<bars.length;i++){
var color="green";
//You can check for bars[i].value and put your conditions here
if(bars[i].value<3){
color="red";
}
else if(bars[i].value<5){
color="orange"
}
else if(bars[i].value<8){
color="yellow"
}
else{
color="green"
}
bars[i].fillColor = color;
}
myObjBar.update(); //update the cahrt
Here is an example working :)

addData() dropped from latest chart.js 2.1.3 - whats up?

I've been reading the docs, and there are ways to replace the data then update the chart:
myLineChart.data.datasets[0].data[2] = 50; // Would update the first dataset's value of 'March' to be 50
myLineChart.update(); // Calling update now animates the position of March from 90 to 50.
https://github.com/chartjs/Chart.js/blob/master/docs/07-Advanced.md
But addData() appears to be gone, am I stuck with making my own addData for local data and then updating the whole chart? or am I missing something.
The update() handles adding data too. Just push your new data / labels into the config object that you passed when creating the chart and then call update()
For instance,
var config = {
type: 'line',
data: {
labels: ["January", "February", "March", "April", "May", "June", "July"],
datasets: [{
label: "My First dataset",
data: [65, 0, 80, 81, 56, 85, 40],
fill: false
}]
}
};
var ctx = document.getElementById("myChart").getContext("2d");
var myChart = new Chart(ctx, config);
setTimeout(function(){
config.data.labels.push('Test');
config.data.datasets[0].data.push(3);
myChart.update();
}, 1000);
Fiddle - http://jsfiddle.net/zpnx8ppb/

Categories