chart.js random weird problems - javascript

this to me makes absolutely no logical sense.
my graph.js was working until it randomly just stopped after passing local storage as a prop. i refactored to make the prop passed in completely unrelated to the local storage... which still shouldn't matter.
for some reason every single number i put into the data field works EXCEPT when i put in props.score/number or ANYTHING reassigned that number. ive never seen anything like it. when i console log number is is 82. it is a number (it is blue in the console) yet when i put it into chart.js it just won't appear.
what the heck is going on?!
this feels like typing 2+2 into a calculator and getting 5. i literally have no idea i have now been trying to figure this out for maybe 4 hours with absolutely no answer. once again...
this error just happened randomly today my app was working fine prior to this...?!
did chart.js change something as of yesterday?
is this a random bug ?
i have never run into such a problem after backtracking for so long. makes no sense.
import {useEffect} from 'react'
import Chart from 'chart.js';
import './BreakDown.css'
const LineChart = (props) => {
const number=props.score ***i am trying to get props.score into the chart js data point.
console.log(number) ****this console logs 82
const newNumber=10+number
console.log(newNumber) ***this console logs 92
useEffect(()=>{
var ctx = document.getElementById('myLineChart');
var myChart = new Chart(ctx, {
type: 'line',
responsive:true,
data: {
labels: ['X', 'IQ', 'X'],
datasets: [{
label: 'Your Score',
data: [0,newNumber,0], ***no matter what i do plug in in either of these numebnrs here doesn't work.
backgroundColor: [
'rgba(54, 80, 235, 0.2)',
'rgba(54, 80, 235, 0.2)',
'rgba(54, 162, 235, 0.2)'
],
borderColor: [
'rgba(255, 99, 132, 1)',
'rgba(54, 162, 235, 1)',
'rgba(255, 206, 86, 1)',
],
borderWidth: 1,
},
{
label: 'Average',
data: [0, 100, 0],
backgroundColor: [
'rgba(54, 162, 235, 0.2)',
'rgba(54, 162, 235, 0.2)',
'rgba(54, 80, 235, 0.2)',
],
borderColor: [
'rgba(255, 99, 132, .5)',
'rgba(255, 99, 132, .5)',
'rgba(255, 99, 132, .5)',
],
borderWidth: 1
}]
},
options: {
scales: {
yAxes: [{
ticks: {
beginAtZero: false,
suggestedMin: 70,
suggestedMax: 160,
stepSize: 10
}
}]
}
}
});
},[])
return (
<div >
<canvas id="myLineChart" width="650" height="400"></canvas>
</div>
)
}
export default LineChart
to make things EVEN more bizarre if i plug in newNumber into the chart it gives me 10 in this case EVEN though console.logging newNumber gives me 92... HUH?!

Your code works fine on the first render for me. I am not 100% sure from your description what you think is going wrong, but 1 problem I see is that useEffect will only run once due to the [] in the second parameter.
If your prop.score updates, useEffect() won't run again, which means your chart won't update.
The main change I did below was add props.score in the array for useEffect, this tells useEffect to run again if props.score changes. You can read more about this in the useEffect docs
import React, { useEffect } from 'react'
import Chart from 'chart.js';
const LineChart = (props) => {
const number = props.score //***i am trying to get props.score into the chart js data point.
console.log(number) //****this console logs 82
const newNumber = 10 + number
console.log(newNumber) //***this console logs 92
useEffect(() => {
var ctx = document.getElementById('myLineChart');
var myChart = new Chart(ctx, {
type: 'line',
responsive: true,
data: {
labels: ['X', 'IQ', 'X'],
datasets: [{
label: 'Your Score',
data: [0, newNumber, 0],
backgroundColor: [
'rgba(54, 80, 235, 0.2)',
'rgba(54, 80, 235, 0.2)',
'rgba(54, 162, 235, 0.2)'
],
borderColor: [
'rgba(255, 99, 132, 1)',
'rgba(54, 162, 235, 1)',
'rgba(255, 206, 86, 1)',
],
borderWidth: 1,
},
{
label: 'Average',
data: [0, 100, 0],
backgroundColor: [
'rgba(54, 162, 235, 0.2)',
'rgba(54, 162, 235, 0.2)',
'rgba(54, 80, 235, 0.2)',
],
borderColor: [
'rgba(255, 99, 132, .5)',
'rgba(255, 99, 132, .5)',
'rgba(255, 99, 132, .5)',
],
borderWidth: 1
}]
},
options: {
scales: {
yAxes: [{
ticks: {
beginAtZero: false,
suggestedMin: 70,
suggestedMax: 160,
stepSize: 10
}
}]
}
}
});
}, [props.score])
return (
<div >
<canvas id="myLineChart" width="650" height="400"></canvas>
</div>
)
}
export default LineChart

Related

Chart Js function (Chart.js) is stuck in a loop

I am trying to use Chart.js in my HTML document(main.html) by calling the the javascript function form a separate javascript file (home.js).
The HTML looks as follows:
{% block head %}
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.6.0/Chart.min.js"></script>
<script type="text/javascript" src="/static/js/home.js"></script>
{% endblock %}
{% block body %}
<div>
<canvas id='myChart'></canvas>
</div>
<script>
Chart(data, document.getElementById('myChart'))
</script>
The js file looks as follows:
function Chart(data, ctx){
console.log("JS")
var myChart = new Chart(ctx, {
type: 'bar',
data: {
labels: ['Red', 'Blue', 'Yellow', 'Green', 'Purple', 'Orange'],
datasets: [{
label: '# of Votes',
data: [12, 19, 3, 5, 2, 3],
backgroundColor: [
'rgba(255, 99, 132, 0.2)',
'rgba(54, 162, 235, 0.2)',
'rgba(255, 206, 86, 0.2)',
'rgba(75, 192, 192, 0.2)',
'rgba(153, 102, 255, 0.2)',
'rgba(255, 159, 64, 0.2)'
],
borderColor: [
'rgba(255, 99, 132, 1)',
'rgba(54, 162, 235, 1)',
'rgba(255, 206, 86, 1)',
'rgba(75, 192, 192, 1)',
'rgba(153, 102, 255, 1)',
'rgba(255, 159, 64, 1)'
],
borderWidth: 1
}]
},
options: {
scales: {
yAxes: [{
ticks: {
beginAtZero: true
}
}]
}
}
});
}
When I do that it somehow keeps executing the the function (ie. stuck in a loop, I checked that by using console.log('JS'). I did not figure out why it keeps doing that. The chart is never displayed.
If I add the function directly in the html in a tag it works flawlessly, but I'd rather want the js separate from the html.
I use flask as web framework and that is where the variable 'data' is coming from. Any tips or ideas?
Thanks and regards
PS: I don't use 'data' at the moment because I don't even get the chart running (it will be the result of db query later.
First, two problems unrelated to your infinite loop problem:
In main.html, the data param you are sending to Chart.js is undefined. Presumably you will fix that in your actual code.
In the selector you send to Chart.js, you are sending the canvas – document.getElementById('myChart') – when you should be sending the canvas context – document.getElementById('myChart').getContext('2d')
Once those are fixed, you could potentially be rendering a chart, but you get an infinite loop because you have called your own function Chart when that's also the name of the Chart.js function (where it says var myChart = new Chart(ctx, ...). Just change your function name to something else.
Here's an example where I just put in an empty array for data and changed your function name to drawChart.
function drawChart(data, ctx){
var myChart = new Chart(ctx, {
type: 'bar',
data: {
labels: ['Red', 'Blue', 'Yellow', 'Green', 'Purple', 'Orange'],
datasets: [{
label: '# of Votes',
data: [12, 19, 3, 5, 2, 3],
backgroundColor: [
'rgba(255, 99, 132, 0.2)',
'rgba(54, 162, 235, 0.2)',
'rgba(255, 206, 86, 0.2)',
'rgba(75, 192, 192, 0.2)',
'rgba(153, 102, 255, 0.2)',
'rgba(255, 159, 64, 0.2)'
],
borderColor: [
'rgba(255, 99, 132, 1)',
'rgba(54, 162, 235, 1)',
'rgba(255, 206, 86, 1)',
'rgba(75, 192, 192, 1)',
'rgba(153, 102, 255, 1)',
'rgba(255, 159, 64, 1)'
],
borderWidth: 1
}]
},
options: {
scales: {
yAxes: [{
ticks: {
beginAtZero: true
}
}]
}
}
});
}
drawChart([], document.getElementById('myChart').getContext('2d'))
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.6.0/Chart.min.js"></script>
<canvas id='myChart'></canvas>
NB: The script error that shows up in the console log is because of cross-origin scripting on StackOverflow and is something you can fix on your own site.

ChartJS: Get value from another another Chart

I have two charts, First chart shows the breakup of Shirt sales.
Second is the comparison of Blue Shirt vs Blue Trouser sales.
I want to import the Blue Shirt value from the first Chart to Second chart.
Here is the Code with two charts:
var ctx = document.getElementById("myChart1").getContext('2d');
var myChart = new Chart(ctx, {
type: 'bar',
data: {
labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"],
datasets: [{
label: 'Shirts',
data: [10, 10, 15, 5, 2, 3],
backgroundColor: [
'rgba(255, 99, 132, 0.2)',
'rgba(54, 162, 235, 0.2)',
'rgba(255, 206, 86, 0.2)',
'rgba(75, 192, 192, 0.2)',
'rgba(153, 102, 255, 0.2)',
'rgba(255, 159, 64, 0.2)'
],
borderColor: [
'rgba(255,99,132,1)',
'rgba(54, 162, 235, 1)',
'rgba(255, 206, 86, 1)',
'rgba(75, 192, 192, 1)',
'rgba(153, 102, 255, 1)',
'rgba(255, 159, 64, 1)'
],
borderWidth: 1
}]
},
options: {
scales: {
yAxes: [{
ticks: {
beginAtZero:true
}
}]
},
}
});
var ctx = document.getElementById("myChart2").getContext('2d');
var myChart = new Chart(ctx, {
type: 'bar',
data: {
labels: ["Blue Shirts", "Blue Trousers"],
datasets: [{
label: 'Sales',
data: [10, 8],
backgroundColor: [
'rgba(255, 99, 132, 0.2)',
'rgba(54, 162, 235, 0.2)',
],
borderColor: [
'rgba(255,99,132,1)',
'rgba(54, 162, 235, 1)',
],
borderWidth: 1
}]
},
options: {
scales: {
yAxes: [{
ticks: {
beginAtZero:true
}
}]
},
}
});
Here is the JSFiddle (https://jsfiddle.net/kingBethal/L8x790fn/15/).
I found this thread describing getting data from click events: Click events on Pie Charts in Chart.js
I made also made a new fiddle here where it logs a chart object containing the chart data on chart click: https://jsfiddle.net/btnL9d2a/16/
myChart1Canvas.onclick = function(evt) {
var activePoints = myChart.getElementsAtEvent(evt);
if (activePoints[0]) {
var chartData = activePoints[0]['_chart'].config.data;
// `chartData` will be an object in the format {'Labels' : Array, 'datasets' : Array}.
console.log(chartData);
}
};
chartData.datasets[0].data is an array of the clicked-on chart's data.

Getting 'Chart is not defined' error when using chart.js in Meteor

I am using the official chart.js atmosphere package in my meteor application. I've tried running an example chart to see if I can pull it up however I am getting an issue saying "ReferenceError: Chart is not defined"
Here are the steps I took to installing the atmosphere package and running the code to produce the chart.
Installed the package with meteor add chart:chart
In my HTML I added the canvas tag calling the chart with it's informaiton
In the JS I added the function that creates the chart along with its relevant information
When I go to the page however, I just get an empty 400x400 image which is the canvas but there is no content there where the chart is supposed to be. Could someone assist me in figuring out what step I'm missing in order to get the chart to appear?
HTML
<template name="Home_page">
<canvas id="myChart" width="400" height="400"></canvas>
</template>
JS
import './home-page.html';
Template.Home_page.onRendered(function homePageOnRendered() {
var ctx = document.getElementById("myChart").getContext("2d");
var myChart = new Chart(ctx, {
type: 'bar',
data: {
labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"],
datasets: [{
label: '# of Votes',
data: [12, 19, 3, 5, 2, 3],
backgroundColor: [
'rgba(255, 99, 132, 0.2)',
'rgba(54, 162, 235, 0.2)',
'rgba(255, 206, 86, 0.2)',
'rgba(75, 192, 192, 0.2)',
'rgba(153, 102, 255, 0.2)',
'rgba(255, 159, 64, 0.2)'
],
borderColor: [
'rgba(255,99,132,1)',
'rgba(54, 162, 235, 1)',
'rgba(255, 206, 86, 1)',
'rgba(75, 192, 192, 1)',
'rgba(153, 102, 255, 1)',
'rgba(255, 159, 64, 1)'
],
borderWidth: 1
}]
},
options: {
scales: {
yAxes: [{
ticks: {
beginAtZero:true
}
}]
}
}
});
});
Ok I forgot to add
import Chart from 'chart.js'
in the top of my js file. That fixed it.

How to draw Horizontal line on Bar Chart Chartjs

I have the following script of drawing bar chart and I wanna add horizontal line on particular y dot. I was trying following example link and I just substituted Chart.types.Line.extend with Chart.types.Bar.extend
but as a result I'm getting can not read property extend of undefined
So can someone help to implement above example which in the link properly or suggest another decision
my source code without horizontal line
var ctx = document.getElementById("myChart");
var myChart = new Chart(ctx, {
type: 'bar',
data: {
labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"],
datasets: [{
label: '# of Votes',
data: [12, 19, 3, 5, 2, 3],
backgroundColor: [
'rgba(255, 99, 132, 0.2)',
'rgba(54, 162, 235, 0.2)',
'rgba(255, 206, 86, 0.2)',
'rgba(75, 192, 192, 0.2)',
'rgba(153, 102, 255, 0.2)',
'rgba(255, 159, 64, 0.2)'
],
borderColor: [
'rgba(255,99,132,1)',
'rgba(54, 162, 235, 1)',
'rgba(255, 206, 86, 1)',
'rgba(75, 192, 192, 1)',
'rgba(153, 102, 255, 1)',
'rgba(255, 159, 64, 1)'
],
borderWidth: 1
}]
},
options: {
scales: {
yAxes: [{
ticks: {
beginAtZero:true
},
}]
},
}
});
You can use Chart.js plugins to do that. Plugins let you handle specific events such as beforeUpdate or afterDraw and are also easy to implement :
Chart.pluginService.register({
afterDraw: function(chart) {
// Code here will be triggered ... after the drawing
}
});
An easy way to do it is to simply draw a line like you would you on a simple canvas element, after everything is drawn in your chart, using the lineTo method.
Here is a small example (and its related code) of how it would look like :
With the answer from #tektiv, your yAxis always starts at 0.
This is a working example without the use of yAxe.min, so
you can use it (for example, with beginAtZero:false) and the yAxe scales automatically with your data.
Line plugin:
var canvas = document.getElementById("barCanvas");
var ctx = canvas.getContext('2d');
Chart.pluginService.register({
afterDraw: function(chart) {
if (typeof chart.config.options.lineAt != 'undefined') {
var lineAt = chart.config.options.lineAt;
var ctxPlugin = chart.chart.ctx;
var xAxe = chart.scales[chart.config.options.scales.xAxes[0].id];
var yAxe = chart.scales[chart.config.options.scales.yAxes[0].id];
ctxPlugin.strokeStyle = "red";
ctxPlugin.beginPath();
lineAt = yAxe.getPixelForValue(lineAt);
ctxPlugin.moveTo(xAxe.left, lineAt);
ctxPlugin.lineTo(xAxe.right, lineAt);
ctxPlugin.stroke();
}
}
});
Chart:
var myChart = new Chart(ctx, {
type: 'bar',
data: {
labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"],
datasets: [{
label: '# of Votes',
data: [12, 19, 3, 5, 2, 3],
backgroundColor: [
'rgba(255, 99, 132, 0.2)',
'rgba(54, 162, 235, 0.2)',
'rgba(255, 206, 86, 0.2)',
'rgba(75, 192, 192, 0.2)',
'rgba(153, 102, 255, 0.2)',
'rgba(255, 159, 64, 0.2)'
],
borderColor: [
'rgba(255,99,132,1)',
'rgba(54, 162, 235, 1)',
'rgba(255, 206, 86, 1)',
'rgba(75, 192, 192, 1)',
'rgba(153, 102, 255, 1)',
'rgba(255, 159, 64, 1)'
],
borderWidth: 1
}]
},
options: {
lineAt: 14,
scales: {
yAxes: [{
ticks: {
beginAtZero:false
}
}]
},
}
});

Chart.js addData is undefined when using SignalR

I'm attempting to call Chart.js's addData method from a signalR callback in order to dynamically add data to a chart based on server inputs. However, when the callback is triggered, the addData method on Chart.js is throwing an exception:
Uncaught TypeError: window.myChart.addData is not a function
Javascript:
var ctx = $("#myChart");
window.myChart = new Chart(ctx, {
type: 'line',
data: {
labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"],
datasets: [{
label: '# of Votes',
data: [12, 19, 3, 5, 2, 3],
backgroundColor: [
'rgba(255, 99, 132, 0.2)',
'rgba(54, 162, 235, 0.2)',
'rgba(255, 206, 86, 0.2)',
'rgba(75, 192, 192, 0.2)',
'rgba(153, 102, 255, 0.2)',
'rgba(255, 159, 64, 0.2)'
],
borderColor: [
'rgba(255,99,132,1)',
'rgba(54, 162, 235, 1)',
'rgba(255, 206, 86, 1)',
'rgba(75, 192, 192, 1)',
'rgba(153, 102, 255, 1)',
'rgba(255, 159, 64, 1)'
],
borderWidth: 1
}]
},
options: {
scales: {
yAxes: [{
ticks: {
beginAtZero: true
}
}]
}
},
responsive: true
});
$(function () {
var chart = $.connection.chartHub;
chart.client.addPointToChart = function () {
window.myChart.addData([20], "Magenta");
};
$.connection.hub.start().done(function () {
chart.server.start();
});
});
C# (hub code)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using Microsoft.AspNet.SignalR;
namespace dvvWeb.Hubs
{
public class ChartHub : Hub
{
public void Start()
{
while (true)
{
Clients.All.addPointToChart();
System.Threading.Thread.Sleep(10000);
}
}
}
}
According to the documentation you should change your dataset directly and call update:
.update(duration, lazy) function to update your datas
// duration is the time for the animation of the redraw in miliseconds
// lazy is a boolean. if true, the animation can be interupted by other animations
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.
I did a little test function on this fiddle:
setInterval(function(e) {
console.log(myDoughnutChart.data.datasets[0]);
myDoughnutChart.data.datasets[0].data.push(15);
myDoughnutChart.update();
}, 1000);
https://jsfiddle.net/Tintin37/weLoqyby/
Opened issue : https://github.com/chartjs/Chart.js/issues/1997
EDIT
For real time chart (I'm using signalr too, I use visjs)
http://visjs.org/examples/graph2d/15_streaming_data.html
Have a great day !

Categories

Resources