How can my Chart.js just update when data in SQL change? - javascript

I build a web app in MVC using SignalR to update real-time data. I can display my chart with real-time data from SQL but it just updates by the time set in setInterval. But now I want my chart to just update when my data in SQL SERVER changes. I have tried many ways but it's not correct. Can you help me with the algorithm? Thank you.
Here is my code :
<!--Chart-->
<script>
var ctx = document.getElementById("percent-chart2");
var colorarray = ['#00b5e9', '#fa4251', '#006400'];
var pre_vals = 0;
//
var myVar = setInterval(GetValue, 1000);
function GetValue() {
var val1 = parseFloat(document.getElementById("tblValue").innerHTML);
var val2 = parseFloat(document.getElementById("tblValue1").innerHTML);
var vals = [val1, val2, 2000];
return vals;
}
if (ctx) {
ctx.height = 209;
var myChart = new Chart(ctx, {
type: 'doughnut',
data: {
datasets: [
{
label: "My First dataset",
//data: [GetValue, GetValue, GetValue],
data: GetValue(),
backgroundColor: [
'#00b5e9',
'#fa4251',
'#006400'
],
hoverBackgroundColor: [
'#00b5e9',
'#fa4251',
'#006400'
],
borderWidth: [
0, 0, 0
],
hoverBorderColor: [
'transparent',
'transparent',
'transparent'
]
}
],
labels: [
'STATION 1',
'STATION 2',
'STATION 3'
]
},
options: {
maintainAspectRatio: false,
responsive: true,
cutoutPercentage: 57,
animation: {
animateScale: true,
animateRotate: true
},
legend: {
display: false,
position: 'bottom',
labels: {
fontSize: 14,
fontFamily: "Poppins,sans-serif"
}
},
tooltips: {
titleFontFamily: "Poppins",
xPadding: 15,
yPadding: 10,
caretPadding: 0,
bodyFontSize: 16,
}
}
});
}
function UpdateChart(datachart, data, color) {
datachart.data.datasets.pop();
datachart.data.datasets.push({
data: data,
backgroundColor: color,
hoverBackgroundColor: color
});
datachart.update();
}
setInterval(function () {
const my_val = GetValue();
//var updatedata = [my_val, my_val, 2000];
var updatedata = my_val;
UpdateChart(myChart, updatedata, colorarray);
}, 10000);
</script>

The way I handle this is by adding a client call with the dataset after the database update has completed. This way you only update when that update is called.
Here is a rough example off the top of my head:
public void UpdateDB(int updatedData)
{
//DB work to commit the updatedData
....
//Query your dataset into an serialized updatedDataset
....
//Call a method to create an array (updatedColors) of colors based on the the Count of updatedDataset
....
//Send data to client(s)
Clients.All.yourclientfunction(updatedDataset, updatedColors);
}

Related

Passing parameters to linechart angular typescript

I want to pass a parameter to chart line based to json iput s data1 instead of var labeltabmles = ['Redddd', 'Blue', 'Yellow', 'Green'];
var datalabel = [1240, 190, 30, 545];
I did the algorithme below in order to get the values of count on variable listcount and get the values of type on variable listtype to configure parameter labels and data of line chart configuration from json file inputs using the code below :
listcount = [];
listtype = [];
......
ngOnInit(): void {
var data1 = [{
"type": "MATH",
"count": 55
}, {
"type": "ENGLISH",
"count": 22
},
{
"type": "SCINETIST",
"count": 18
}];
for (var key in data1) {
var typeelement = data1[key]["type"];
var countelemtn = data1[key]["count"];
this.listtype.push(typeelement);
this.listcount.push(countelemtn);
console.log(this.listcount);
console.log(this.listtype);
}
console.log(this.listcount);
console.log(this.listtype);
var labeltabmles = ['Redddd', 'Blue', 'Yellow', 'Green'];
var datalabel = [1240, 190, 30, 545];
const myChart1 = new Chart("myChartline", {
type: 'line',
data: {
labels: labeltabmles,
datasets: [{
label: '# of Votes',
data: datalabel,
backgroundColor: "#007ee7",
borderColor: "#007ee7",
borderWidth: 1
}]
},
options: {
scales: {
y: {
beginAtZero: true
}
}
}
});
i want to configure the var labeltabmles = ['Redddd', 'Blue', 'Yellow', 'Green'];
var datalabel = [1240, 190, 30, 545]; using the variables listcount , listtype
where the result of this two array are following the code enter image description here
i need your help to pass listcount and listtype as paramter to datalabel and data of the chart
i tried but the apped didnt happen the this.listype and this.listcount still empty;
var labeltabmles = this.listcount ;
var datalabel = this.listype;
Thanks for your support and help
i find the solution by :
-using the TYPELIST: any = []; COUNTLIST: any = [];
-and update the variable used on push function on the for iteration
for (var key in data1) {
var typeelement = this.contentype[key]["type"];
var countelemtn = this.contentype[key]["count"];
this.TYPELIST.push(typeelement);
this.COUNTLIST.push(countelemtn);
}
const myChart1 = new Chart("myChartline", {
type: 'line',
data: {
labels: this.TYPELIST,
datasets: [{
label: '# of Votes',
data: this.COUNTLIST,
backgroundColor: "#007ee7",
borderColor: "#007ee7",
borderWidth: 1
}]
},
options: {
scales: {
y: {
beginAtZero: true
}
}
}
});

How to use a Data Array within a Chart JS dataset?

I have the following JSON, that I want to insert a chart using Chart JS:
{"Results":[{"Data":"25/02/2021","Valor":18},{"Data":"24/02/2021","Valor":2993},{"Data":"23/02/2021","Valor":1936},{"Data":"22/02/2021","Valor":1844},{"Data":"21/02/2021","Valor":1114},{"Data":"20/02/2021","Valor":1060},{"Data":"19/02/2021","Valor":1134}]}
And I created a function to load this JSON into an Array:
function ShowData(jsonObj) {
var bases = jsonObj['Results'];
var Date = [];
var Val = [];
for (var i = bases.length-1; i >= 0; i--) {
Date.push([bases[i].Data]);
Val.push([bases[i].Valor]);
}
}
When I load this Array into the Chart, As below:
var chartGraph = new Chart(ctx,{
type:'line',
data:{
labels: Date,
datasets: [
{
label: "Lbl Name",
data: Val,
borderWidth: 6,
borderColor: 'rgba(77,166,253, 0.85)',
backgroundColor: 'transparent'
}
]
},
options: {
title: {
display: true,
fontSize: 20,
text: 'Chart Name'
},
legend: {
display: true,
position: 'right',
labels: {
fontColor: '#666'
}
}
}
})
No information on "datasets" appears to me, only the "label", what is the mistake I am making?
Graphic Image
Try to split series and data, something like:
function splitData(type) {
return json.Results.map(v => v[type]);
}
// your Chart.js config
data: {
labels: splitData('Date'),
datasets: [
{
// ...otherProps,
data: splitData('Valor')
}
]
}
You cant use Date as variable name since its a build in class. Also from my testing couldnt reference the vars inside the function. But the real problem with your code is that you push an array to the val array. This made it an array containing arrays. This is not supported. If you change your code to the sample below it will work
let date = [];
let val = [];
function ShowData(jsonObj) {
var bases = jsonObj['Results'];
date = [];
val = [];
for (var i = bases.length-1; i >= 0; i--) {
date.push(bases[i].Data);
val.push(bases[i].Valor);
}
}
var chartGraph = new Chart(ctx,{
type:'line',
data:{
labels: Date,
datasets: [
{
label: "Lbl Name",
data: Val,
borderWidth: 6,
borderColor: 'rgba(77,166,253, 0.85)',
backgroundColor: 'transparent'
}
]
},
options: {
title: {
display: true,
fontSize: 20,
text: 'Chart Name'
},
legend: {
display: true,
position: 'right',
labels: {
fontColor: '#666'
}
}
}
})

Charts Js Stacked Bar Graph displays no values?

I have a javascript map like this..
var Severity = {
3M:[0, 3, 1, 0, 0],
5T:[0, 0, 1, 0, 0],
6S:[0, 0, 2, 0, 0]
}
And a JS function to call Stacked Chart Bar. Here I have a created a JS function which takes id and a map from jsp page. Map structure is same as above defined. I want to display graph where in x axis the data is the keys in map and in y axes is the stacked up data of 5 elements.
function StackedBar(id,Severity) {
var label = Object.keys(Severity); // getting the labels
var Critical = [];
var High = [];
var Medium = [];
var Low = [];
var Others = [];
for(let i=0;i<label.length;i++){ //assigning the data to arrays created
Critical.push(Severity[label[i]][0]);
High.push(Severity[label[i]][1]);
Medium.push(Severity[label[i]][2]);
Low.push(Severity[label[i]][3]);
Others.push(Severity[label[i]][4]);
}
var ctxL = document.getElementById(id).getContext('2d'); //id from the html canvas
var chart = new Chart(ctxL, {
type: 'bar',
data: {
labels: label,
datasets: [
{
label: 'Critical',
data: Critical,
backgroundColor: '#aa000e'
},
{
label: 'High',
data: High,
backgroundColor: '#e65905'
},
{
label: 'Medium',
data: Medium,
backgroundColor: '#e00ce6'
},
{
label: 'Low',
data: Low,
backgroundColor: '#b8ab16'
},
{
label: 'Others',
data: Others,
backgroundColor: '#00aaaa'
}
]
},
options: {
responsive: true,
legend: {
position: 'right'
},
scales: {
xAxes: [{
stacked: true
}],
yAxes: [{
stacked: true
}]
}
}
});
}
Here graph displays and i get label in x axes...but graph values doesn't show and i get following error..
Html
<canvas id="overall"></canvas>
<script>StackedBar('overall',Overall);</script>
I wanted to know what went wrong and want me to help fix this issue...
I put the above together into one file and it works (although I had to change "Overall" to "Severity" in the call). So I'd expect that something you are using might not match your example above.
The version I used:
<html>
<body>
<canvas id="overall"></canvas>
</body>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.3/Chart.min.js"></script>
<script>
var Severity = {
"3M": [0, 3, 1, 0, 0],
"5T": [0, 0, 1, 0, 0],
"6S": [0, 0, 2, 0, 0]
};
</script>
<script>
function StackedBar(id, Severity) {
var label = Object.keys(Severity); // getting the labels
var Critical = [];
var High = [];
var Medium = [];
var Low = [];
var Others = [];
for (let i = 0; i < label.length; i++) { //assigning the data to arrays created
Critical.push(Severity[label[i]][0]);
High.push(Severity[label[i]][1]);
Medium.push(Severity[label[i]][2]);
Low.push(Severity[label[i]][3]);
Others.push(Severity[label[i]][4]);
}
var ctxL = document.getElementById(id).getContext('2d'); //id from the html canvas
var chart = new Chart(ctxL, {
type: 'bar',
data: {
labels: label,
datasets: [
{
label: 'Critical',
data: Critical,
backgroundColor: '#aa000e'
},
{
label: 'High',
data: High,
backgroundColor: '#e65905'
},
{
label: 'Medium',
data: Medium,
backgroundColor: '#e00ce6'
},
{
label: 'Low',
data: Low,
backgroundColor: '#b8ab16'
},
{
label: 'Others',
data: Others,
backgroundColor: '#00aaaa'
}
]
},
options: {
responsive: true,
legend: {
position: 'right'
},
scales: {
xAxes: [{
stacked: true
}],
yAxes: [{
stacked: true
}]
}
}
});
}
</script>
<script>StackedBar('overall', Severity);</script>
</html>

Live Update Callback -> afterTitle with Array via JSON file

I'm working on a chart, I'm live updating the Chart every 5 seconds that the data comes in. I could manage to get the info from the database and update it really easy, but I just came across a problem with involves setting a path to a part of the chart, in the case: options->tootltips->callbacks->afterTitle and inside of it create an array and pass the array from the JSON to an array inside the callback.
What I would need to do, In a really brief way is, since I already made a function to update the info from my Data and Labels, somehow I will need to make inside this function, a path to the afterTitle, than I will be able send the fifth array, in with stores the data. As you can see in my function, I could manage to do it for the data and label.
I can't have another function that updates, so basically I can't have 2 loadData(), because it makes the Chart blink every time it updates, and that's not what I'm aiming for (The chart can't blink).
Inside this patch, I made an example that didn't work, with is the //:
$.getJSON('loadchart.php', function(response) {
myLineChart.data.datasets[0].data = response[0];
myLineChart.data.datasets[1].data = response[1];
myLineChart.data.datasets[2].data = response[2];
myLineChart.data.datasets[3].data = response[3];
myLineChart.data.labels = response[4];
//The response array that I need is response[5];
//myLineChart.options.tooltips.callbacks[1] = return response[tooltipItem[0]['index']];
myLineChart.update();
});
All my Chart so you can see the path:
<script>
function loadData() {
$.getJSON('loadchart.php', function(response) {
myLineChart.data.datasets[0].data = response[0];
myLineChart.data.datasets[1].data = response[1];
myLineChart.data.datasets[2].data = response[2];
myLineChart.data.datasets[3].data = response[3];
myLineChart.data.labels = response[4];
myLineChart.update();
});
}
loadData();
setInterval(loadData, 5000);
var lbl = [];
var ctx1 = document.getElementById('mychart1').getContext('2d');
var myLineChart = new Chart(ctx1, {
type: 'line',
data: {
labels: lbl,
datasets: [
{
label: "Corrente 1",
data: [],
borderWidht: 6,
borderColor: 'red',
backgroundColor: 'transparent'
},
{
label: "Corrente 2",
data: [],
borderWidht: 6,
borderColor: 'blue',
backgroundColor: 'transparent'
},
{
label: "Corrente 3",
data: [],
borderWidht: 6,
borderColor: 'green',
backgroundColor: 'transparent'
},
{
label: "Corrente Total",
data: [],
borderWidht: 6,
borderColor: 'black',
backgroundColor: 'transparent'
},
]
},
options: {
animation:{
update: 0
},
scales: {
yAxes: [{
ticks: {
beginAtZero: true
}
}],
xAxes: [{
gridLines: {
display: false
}
}]
},
title: {
display: true,
fontSize: 20,
text: "Gráfico das Correntes"
},
labels: {
fontStyle: "bold",
},
layout: {
padding: {
left: 0,
right: 0,
top: 0,
bottom: 0
}
},
tooltips: {
enabled: true,
mode: 'single',
responsive: true,
backgroundColor: 'black',
titleFontFamily: "'Arial'",
titleFontSize: 14,
titleFontStyle: 'bold',
titleAlign: 'center',
titleSpacing: 4,
titleMarginBottom: 10,
bodyFontFamily: "'Mukta'",
bodyFontSize: 14,
borderWidth: 2,
borderColor: 'grey',
callbacks:{
title: function(tooltipItem, data) {
return data.labels[tooltipItem[0].index];
},
afterTitle: function(tooltipItem, data) {
var tempo = [];
return tempo[tooltipItem[0]['index']];
},
label: function(tooltipItem, data) {
var label = data.datasets[tooltipItem.datasetIndex].label || '';
if (label) {
label += ': ';
}
label += (tooltipItem.yLabel)+"A";
return label;
}
}
},
aspectRatio: 1,
maintainAspectRatio: false
}
});
</script>
The part I need is this one:
afterTitle: function(tooltipItem, data) {
var tempo = [];
return tempo[tooltipItem[0]['index']];
This will display a clock but you can also set it to 5000 seconds and call your chart update. Which i would suggest to put in some kind of AJAX to let it work asynchonous.
<!DOCTYPE html>
<html>
<head>
<script>
function startTime() {
var today = new Date();
var h = today.getHours();
var m = today.getMinutes();
var s = today.getSeconds();
m = checkTime(m);
s = checkTime(s);
document.getElementById('txt').innerHTML =
h + ":" + m + ":" + s;
var t = setTimeout(startTime, 500); //<---- !!!
}
function checkTime(i) {
if (i < 10) {i = "0" + i}; // add zero in front of numbers < 10
return i;
}
</script>
</head>
<body onload="startTime()">
<div id="txt"></div>
</body>
</html>
As you mention in afterTitle function you want to create an array and pass the array from the JSON to an array inside the callback, and the missing part is you are creating an array tempo and treating it like an object tempo[tooltipItem[0]['index']];, but what you need to do is push this object tooltipItem[0]['index'] to tempo array.
Please replace afterTitle function with the below code
afterTitle: function(tooltipItem, data) {
var tempo = [];
return tempo.push(tooltipItem[0]['index']);

chart.js ajax pushing another dataset always "undefined"

Following is my javascript Code, but the only thing really relevant is the last function. I want to update the Chart to add another dataset, without reloading the Page. But for reason the added dataset is always undefined. The commented-out line, which uses the exact same array of data, on the other hand works. Since I'm new to javascript I'm not sure, if I missed something obvious, or if chart.js just doesn't support this kind of thing at all.
const CHART = document.getElementById("lineChart");
var dts1 = [
{
label: "Abfall gesamt",
data: Abfall_gesamt,
}
];
var dts2 = [
{
label: "Abfall schadstoffhaltiger",
data: Abfall_schadstoff,
}
];
var lineChart = new Chart(CHART, {
type: 'line',
data: {
labels: Jahr,
datasets: dts1
}
});
function myFunction(){
//lineChart.data.datasets[0].data = Abfall_schadstoff;
lineChart.data.datasets.push(dts2);
lineChart.update();
}
The issue is, you are defining your datasets (dts1 and dts2) as an array. They should be an object, like so ...
var dts1 = {
label: "Abfall gesamt",
data: Abfall_gesamt,
};
var dts2 = {
label: "Abfall schadstoffhaltiger",
data: Abfall_schadstoff,
};
and then, when generating the chart, set datasets value as ...
datasets: [dts1]
ᴅᴇᴍᴏ
const CHART = document.getElementById("lineChart");
var Abfall_gesamt = [1, 2, 3];
var Abfall_schadstoff = [4, 5, 6]
var dts1 = {
label: "Abfall gesamt",
data: Abfall_gesamt,
backgroundColor: 'rgba(255, 0, 0, 0.2)'
};
var dts2 = {
label: "Abfall schadstoffhaltiger",
data: Abfall_schadstoff,
backgroundColor: 'rgba(0, 0, 255, 0.2)'
};
var lineChart = new Chart(CHART, {
type: 'line',
data: {
labels: ['Jahr', 'Mahr', 'Kadr'],
datasets: [dts1]
},
options: {
responsive: false,
scales: {
yAxes: [{
ticks: {
beginAtZero: true,
stepSize: 1
}
}]
}
}
});
function myFunction() {
//lineChart.data.datasets[0].data = Abfall_schadstoff;
lineChart.data.datasets.push(dts2);
lineChart.update();
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.5.0/Chart.min.js"></script>
<button id="add" onclick="myFunction()">Add Dataset</button>
<canvas id="lineChart" height="190"></canvas>

Categories

Resources