Chart.js addData is undefined when using SignalR - javascript

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 !

Related

It seems I cannot use JS code from CDN import

I have two HTML buttons, each linked to a specific JavaScript function. The first button triggers a function codded like so:
function add() {
var newScript = document.createElement("script");
newScript.src = "https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.4/Chart.js";
document.head.appendChild(newScript);
}
The second button triggers the following function:
function draw() {
const ctx = document.getElementById('myChart').getContext('2d');
const 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: {
y: {
beginAtZero: true
}
}
}
});
In function number 2, I am using a sample from www.chartjs.org. To work, it needs the page to have loaded the script referred to in the first function.
After clicking on the button 1 then on the button 2, I am expecting to see in my head element a script element, src=https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.4/Chart.js, which I do see, via the browser console.
On my page, I am expecting to see (after clicking on my second button) a graph, produced by the ChartJS code. This very element is missing. Instead, I have an error in my console, saying: 'Chart is not defined at HTMLButtonElement.draw'
Why do I have this error? Why is my chart not showing up?
Thank you for stopping by :) (y)
One hacky solution is to just include the entire script in your function. i.e.
function add() {
/*!
* Chart.js v2.9.4
* https://www.chartjs.org
* (c) 2020 Chart.js Contributors
* Released under the MIT License
*/
//The entire contents of https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.4/Chart.min.js pasted here
}
Just add html script element, before the your script is evaluated.
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.4/Chart.js"></script>
<script>
function draw() {
// your draw function
}
</script>

Installing chartjs in project without npm, bower or CDN

I am working on a graph page for a project and my client does not want me to use npm, bower or CDN. so my question is how would I use the chartjs library without using these options?
I tried using it this way:
var Chart = require(['../chartjs/Chart.js']);
var ctx = document.getElementById("bar-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: {
scales: {
yAxes: [{
ticks: {
beginAtZero: true
}
}]
}
}
});
but I keep getting the following error:
Uncaught Error: Script error for "../chartjs/Chart.js".
Am I missing a step?
Try this
import chart from './chart';
console.log(chart);

Chart.js passing value data dynamic

I am want to use data and level dynamic by ajax, so i am using as below but not working.
My ajax return data in json_encode of php.
My code is:
success: function (result) {
result = JSON.parse(result);
var labels = result['labels'];
var data = result['data'];
//console.log(data);
var ctx = document.getElementById("chartbtc");
var myChart = new Chart(ctx, {
type: 'line',
data: {
labels: [labels],
datasets: [{
label: 'Market Price (USD)',
data: [data],
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: {
responsive: true,
maintainAspectRatio: false,
scales: {
yAxes: [{
ticks: {
beginAtZero: false
}
}]
}
}
});
}
But chart is not generating:
Ajax result is:
{"labels":"13-Nov-2017, 14-Nov-2017, 15-Nov-2017, 16-Nov-2017, 17-Nov-2017, 18-Nov-2017, 19-Nov-2017, 20-Nov-2017, 21-Nov-2017, 22-Nov-2017, 23-Nov-2017, 24-Nov-2017, 25-Nov-2017, 26-Nov-2017, 27-Nov-2017, 28-Nov-2017, 29-Nov-2017, 30-Nov-2017, 01-Dec-2017, 02-Dec-2017, 03-Dec-2017, 04-Dec-2017, 05-Dec-2017, 06-Dec-2017, 07-Dec-2017, 08-Dec-2017, 09-Dec-2017, 10-Dec-2017, 11-Dec-2017, 12-Dec-2017","data":"6550.22, 6635.41, 7301.42, 7815.03, 7786.88, 7817.14, 8007.65, 8255.59, 8059.8, 8268.03, 8148.94, 8250.97, 8707.4, 9284.14, 9718.29, 9952.5, 9879.32, 10147.37, 10883.91, 11071.36, 11332.62, 11584.82, 11878.43, 13540.98, 16501.97, 16007.43, 15142.83, 14869.8, 16762.11, 17276.39"}
Since you have provided your ajax result, this will not work with the chart generation. In your case result["labels"] is a string and you are just making a list with 1 element which is the whole string(which is not valid for the labels property and will not work). What you should do is split the string, format it correctly and then supply it as a list to the labels property. Easiest way would be to use the split() function, and in your case you could split by ", ". Although I would recommend to implement a better response if its possible (have it something like so: {"labels": ["13-Nov-2017", "14-Nov-2017", ...]}).
Hope this helps!
For the first time you can fill the chart with your own value, but when it is coming for dynamically appending data then you should remove the canvas element and regenerate it. So that your data will get appended dynamically on chart.
You can try something like this.
<canvas id="chartbtc" class="canvasChart"></canvas>
<script>
dynamicDataAppendOnChart(labels, data); // On page loading you will be having your own data so you can pass them, or if you want that to be happen with ajax when page loading itself you can trigger the click event.
$('#btnClick').trigger('click');
// You will be calling the function with click event...
$('#btnClick').on('click', function () {
var data = '', labels = '';
$.ajax({
url: url,
type: "POST",
data: data,
async: isAsync,
success: function (result) {
result = JSON.parse(result);
labels = result['labels'];
data = result['data'];
}
});
dynamicDataAppendOnChart(labels, data); // Now you can call the function by passing labels and data
});
function dynamicDataAppendOnChart() {
$('#chartbtc').remove();
$('#appendTheCanvasElement').append('<canvas id="chartbtc" class="canvasChart"><canvas>'); // This would create new canvas element every time and removes the older one.
var ctx = document.getElementById("chartbtc");
var myChart = new Chart(ctx, {
type: 'line',
data: {
labels: [labels],
datasets: [{
label: 'Market Price (USD)',
data: [data],
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: {
responsive: true,
maintainAspectRatio: false,
scales: {
yAxes: [{
ticks: {
beginAtZero: false
}
}]
}
}
});
}
</script>
Try This.
Declare label and data as
var labels = result['labels'].split(","); // Return Array of Strings Of labels
var data = JSON.parse("[" + result['data'] + "]");// return array of data
Chage
labels: [labels],
data: [data],
to
labels: labels,
data: data,
Because it already in array

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
}
}]
},
}
});

Need help Chart.js in asp.net mvc

A few days can make a graph, we need your guidance.
Arrow displays the objects, but on the chart nothing is displayed. The search was not successful.
My models:
public class Voting
{
public int Id { get; set; }
public string Name { get; set; }
public int Voice { get; set; }
public DateTime DateVote { get; set; }
public string IpAdress { get; set; }
}
My controller:
[HttpGet]
public JsonResult GetVotings()
{
List<Voting> votings = db.Votings.ToList();
return Json(votings, JsonRequestBehavior.AllowGet);
}
Probably the main problem in the script calling the data did. While it is possible the controller is not properly configured to output data, will be very glad of your help.
My View:
<canvas id="ChartVote" width="300" height="200"></canvas>
<script type="text/javascript" charset="utf-8">
$(function () {
$.ajax({
type: "GET",
contentType: "application/json; charset=utf-8",
dataType: 'json',
url: '/Chart/GetVotings',
}).done(function (votings) {
console.log(votings);
$.each(votings, function (index, data) {
myChart.labels.push(data.Name);
myChart.datasets[0].data.push(data.Voice);
});
});
});
var ctx = document.getElementById("ChartVote");
var myChart = new Chart(ctx, {
type: 'bar',
data: {
labels: [],
datasets: [{
label: '# of Votes',
data: [],
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
}
}]
}
}
});
</script>
Your code has few problems ! First of all, inside your $.each you are trying to access labels property of myChart. But you did not define what myChart variable is. So you are going to get an undefined error!
Another thing to think about is, your ajax call is asynchronous. It may take a long time to get the data. So whenever you get the data, you need to execute the code to render the chart with that data. I suggest you move that code to a method and call that method in your ajax call's success/done event.
This should work.
function renderChart(labels, voice) {
var ctx = document.getElementById("ChartVote");
var myChart = new Chart(ctx, {
type: 'bar',
data: {
labels: labels,
datasets: [{
label: '# of Votes', data: voice,
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 }
}]
}
}
});
}
Now in your ajax call's done event, you can pass the label array and data array to your RenderChart method.
$(function(){
$.ajax({
type: "GET",
url: '#Url.Action("GetVotings","Chart")',
}).done(function (votings) {
var labelsArray = [];
var dataArray = [];
$.each(votings, function (index, data) {
labelsArray.push(data.Name);
dataArray.push(data.Voice);
});
renderChart(labelsArray, dataArray);
});
});

Categories

Resources