Use an array as chart values - javascript

I need an array with chart values, I obtained one but after exiting from the function it became blank, here's what happens: Example
function AddvotoTec(votor) {
class Avg {
constructor() {}
static average(votor) {
var total = 0;
var count = 0;
jQuery.each(votor, function(index, value) {
total += value;
count++;
});
return total / count;
}
}
var mvoti = Avg.average(votor);
var mvoti = Math.round((mvoti + Number.EPSILON) * 10) / 10;
const myJSON = JSON.stringify(mvoti);
voti(myJSON);
}
var allvoti = [];
function voti(Voti) {
allvoti.push(Voti);
}
const data = {
labels: labels,
datasets: [{
label: 'My First dataset',
backgroundColor: [
'rgb(255, 132, 0)'
],
borderColor: 'rgb(255, 99, 132)',
data: allvoti,
}]
};
The chart that I used is Chart.js.

Related

chart.js labels Left to Right

i want to invert labels from Left to Right.
what do i have?
a JSON File in which the data is coming from Google Sheet's App Script.
i Have Created a chart with the help of this JSON file and Chart.js
in this chart the Levels which is time is printed right to left.
What Do i need?
i want to print the levels from Left to Right.
Google Sheet App Script Code
labels Left to Rightfunction doGet(e) {
var sheet = SpreadsheetApp.getActive();
var nse = sheet.getSheetByName("Sheet3");
var data = [];
var rlen = nse.getLastRow();
var clen = nse.getLastColumn();
var rows = nse.getRange(1, 1, rlen, clen).getDisplayValues(); // Modified
for (var i = 1; i < rows.length; i++) {
var datarow = rows[i];
var record = {};
for (var j = 0; j < clen; j++) {
record[rows[0][j]] = datarow[j];
}
data.push(record);
}
var result = JSON.stringify(data);
return ContentService.createTextOutput(result).setMimeType(ContentService.MimeType.JSON);
}
<div style="overflow: scroll;">
<canvas width="900" height="400" id="myChart"></canvas>
</div>
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/chart.js/dist/chart.umd.min.js"></script>
<script>
// setup
const data = {
labels: [],
datasets: [{
label: 'Nifty_PCR_COI',
data: [],
backgroundColor: [
'rgba(255, 26, 104, 0.2)'
],
borderColor: [
'rgba(255, 26, 104, 1)'
],
tension: 0.4,
},{
label: 'Bank_Nifty_PCR_COI',
data: [],
backgroundColor: [
'rgba(54, 162, 235, 0.2)'
],
borderColor: [
'rgba(54, 162, 235, 1)'
],
tension: 0.4,
}]
};
// config
const config = {
type: 'line',
data,
options: {
animation: false,
responsive: false,
scales: {
y: {
beginAtZero: true,
position: 'right'
}
}
}
};
// render init block
const myChart = new Chart(
document.getElementById('myChart'),
config
);
//Json Fetch
getData();
async function getData() {
const response = await fetch(
'https://script.googleusercontent.com/macros/echo?user_content_key=r9CiwwP04Rh83CglKNwLbJw3zKlvAIWVj4Yf9a5cT3CPRmlxaBB9bOAMnkFV2os4ee10iaj9S7HNOU5axJWhdXmuYbHPVyWnm5_BxDlH2jW0nuo2oDemN9CCS2h10ox_1xSncGQajx_ryfhECjZEnC4mxGG_R4juVl897H-HHcU5jBSu36oRyKZzBJteCuzXZ2p8eeHkRfjTV-mrMKhBOgim2y6bAoCZpSiZg9-Rh7EUjhE06fNngtz9Jw9Md8uu&lib=MQ0aMrcKwzFLX_7mD1gjcTxV-kV6j6m2N');
const jsondata = await response.json();
length = jsondata.length;
labels = [];
Nifty_PCR_COI = [];
Bank_Nifty_PCR_COI = [];
for (i = 0; i < length; i++) {
labels.push(jsondata[i].TimeCOI);
Nifty_PCR_COI.push(jsondata[i].Nifty_PCR_COI);
Bank_Nifty_PCR_COI.push(jsondata[i].Bank_Nifty_PCR_COI);
myChart.config.data.labels = labels;
myChart.config.data.datasets[0].data = Nifty_PCR_COI;
myChart.config.data.datasets[1].data = Bank_Nifty_PCR_COI;
myChart.update();
}
}
setInterval(getData, 5000)
</script>

Is there a better way to create an 'n' number of charts in ChartJS and ASP.NET C#?

EDIT: I have narrowed it down to something like this:
for (i = 0; i < data.length; i++) {
const newCanvas = document.createElement("canvas");
newCanvas.id = data[i].design_name;
const currentDiv = document.getElementById("chartSpace");
var parentDiv = document.getElementById("gridHere");
parentDiv.insertBefore(newCanvas, currentDiv);
createChart([data[i].design_name], [data[i].design_start, data[i].design_end]);
}
With the create chart making the chart id = to the array 'labels':
const myChart = new Chart(
document.getElementById(labels),
config
);
I am attempting to create a tool that creates an 'n' number of charts in ChartJS and save each of them as images. Currently, designButtonClick() sends the 'event_fky' value to
getDesigns(event_fky) in my controller. This method returns all designs with that foreign key. In turn, the chart plots each design on the chart. I need to evolve this into
something that can make a group individual charts for each design based on how many designs there are. My current solution, still conceptual, is to have methods in my controller
create chart variables 'chartData [data here]' and 'labels[datahere]' while looping through the designs returned from getDesigns, and sending those back to the JS script createChart
'n' number of times for each design. It would also send html chart/html element ids based on the design_name attribute to send back to createChart. This way, it is create a unique
chart 'n' number of times.
To save the charts as images, I would use the same set of element ids generated by getDesigns to send the charts to images using JS' toBase64Image() function and saving them to the
user's system.
Is this the best way of solving this problem? Or is this spaghetti, and is there a better method for this? My attempts to find better online answers have only resulted in docs on
updating one chart dynamically, not creating a dynamic number of charts. Much help is appreciated, code is below as well as a screenshot of the current chart output.
JavaScript:
var labels = [];
var cData = [];
function designButtonClick() {
var event_fky = 3;
$.ajax({
url: 'Tree/getDesigns',
type: 'POST',
data: { event_fky }
}).done(function (data) {
for (i = 0; i < data.length; i++) {
labels.push(data[i].design_name);
cData.push([data[i].design_start, data[i].design_end])
}
createChart(labels, cData);
});
}
function createChart(labels, cData) {
const data = {
labels: labels,
datasets: [{
barThickness: 2,
categoryPercentage: .5,
label: 'Design Time',
data: cData,
backgroundColor: [
'rgba(255, 26, 104, 0.2)'
],
borderColor: [
'rgba(255, 26, 104, 1)'
],
borderWidth: 1,
borderSkipped: false,
borderRadius: 20
}]
};
const config = {
type: 'bar',
data,
options: {
indexAxis: 'y',
scales: {
y: {
beginAtZero: true
},
x: {
min: 0,
max: 6000,
ticks: {
stepSize: 1000
}
}
}
}
};
const myChart = new Chart(
document.getElementById('myChart'),
config
);
}
C# Controller:
public ActionResult getDesigns(int? event_fky)
{
var designs = from e in _context.designs
where (event_fky.HasValue ? e.event_fky == event_fky : e.event_fky == null)
select new
{
design_pky = e.design_pky,
design_name = e.design_name,
design_start = e.design_start,
design_end = e.design_end
};
return this.Json(designs, JsonRequestBehavior.AllowGet);
}
Designs Table:
--------Design--------
design_pky |int
event_fky |int
design_name |varchar
design_start |number
design_end |number
Screenshot of Chart
This is a working answer for the javascript:
var eventList = function () {
var tmp = null;
$.ajax({
'async': false,
url: 'Tree/getEventIDs',
type: 'POST',
data: {},
'success': function (data) {
tmp = data;
}
});
return tmp;
}();
for (var i = 0; i < eventList.length; i++) {
event_fky = eventList[i].event_pky;
event_name = eventList[i].event_name;
event_length = eventList[i].event_end;
var designList = function () {
var tmpi = null;
$.ajax({
'async': false,
url: 'Tree/getDesigns',
type: 'POST',
data: {event_fky},
'success': function (data1) {
tmpi = data1;
}
});
console.log(event_fky);
console.log(tmpi);
return tmpi;
}();
var dLabels = [];
var dLengths = [];
for (var j = 0; j < designList.length; j++) {
dLabels.push(designList[j].design_name);
dLengths.push([designList[j].design_start, designList[j].design_end]);
}
const newCanvas = document.createElement("canvas");
newCanvas.id = event_name;
const currentDiv = document.getElementById("chartSpace");
var parentDiv = document.getElementById("gridHere");
parentDiv.insertBefore(newCanvas, currentDiv);
if (dLabels.length != 0) {
createChart(dLabels, dLengths, event_name, event_length);
}
}
}
function createChart(labels, cData, evName, evLen) {
// setup
const data = {
labels: labels,
datasets: [{
barThickness: 4,
categoryPercentage: .5,
label: evName,
data: cData,
backgroundColor: [
'rgba(' + Math.random() * 85 + ', ' + Math.random() * 170 + ', ' + Math.random() * 255 + ', 1)'
],
borderColor: [
'rgba(255, 26, 104, 1)'
],
borderWidth: 0,
borderSkipped: false,
borderRadius: 20
}]
};
// config
const config = {
type: 'bar',
data,
options: {
indexAxis: 'y',
scales: {
y: {
beginAtZero: true
},
x: {
min: 0,
max: evLen,
ticks: {
stepSize: 100
}
}
}
}
};
// render init block
const myChart = new Chart(
document.getElementById(evName),
config
);
return myChart;
}

Risers or bars of Dynamically built ChartJs from json not aligning to bottom of y axis

I have strange behaviour from bars or risers in a dynamically built Chartjs chart.
They don't begin at point 0 on the y-axis and not all of them show.
I have tried a variety of ways as found here or other forums, but no success.
Please help.
The code to build it is from json ex ajax to MVC Controller/Action.
chartSetup.jsonDataSets = new List<ChartDataset>();
ChartDataset jsonDataSets = new ChartDataset
{
data = "[408, 547, 675, 534]",
label = "Actual",
backgroundColor = "#8e5ea2"
};
chartSetup.jsonDataSets.Add(jsonDataSets);
jsonDataSets = new ChartDataset
{
data= "[350, 447, 725, 534]",
label = "Budgeted",
backgroundColor = "red"
};
chartSetup.jsonDataSets.Add(jsonDataSets);
If I hardcode particularly the datasets, for the chart, then no problem.
var type = 'bar';
var xLabels = ["May", "Jun", "Jul", "Aug", "Sept"];
var topTitle = { display: true, text: 'Maintenance Costs', fontStyle: 'bold', fontSize: 18, fontColor: 'white' };
var canvasTyreCostsChart = $("#canvasMaintenanceBar").get(0).getContext("2d");
var datasources = [
{
label: "Budgeted",
backgroundColor: 'red',
data: [133, 221, 783, 1078]
},
{
label: "Actual",
backgroundColor: "#8e5ea2",
data: [408, 547, 675, 734]
}
];
var regionalCountCostBar = new Chart(canvasTyreCostsChart,
{
type: type,
data: {
labels: xLabels,
datasets: datasources,
},
options:
{
responsive: true,
title: topTitle,
legend: { position: 'bottom' },
}
});
But done dynamically the bars float above the zero point on the y axis.
Here's the code.
datasources = jsonData['jsonDataSets'];
var dynamicChartCanvas = $("#canvas-" + columnID).get(0).getContext("2d");
var xLabelsArr = [];
$.each(xLabels, function (key, val)
{
var rec = xLabels[key];
xLabelsArr.push(rec['label']);
});
var label;
var backgroundColor;
var data2 = "";
var data3 = [];
var DS = [];
var dataSource2;
// Extract the individual elements
$.each(datasources, function (key, val)
{
var rec = datasources[key];
$.each(rec, function (key, val)
{
if (key == "label")
{
label = val;
}
if (key == "backgroundColor")
{
backgroundColor = val;
}
if (key == "data")
{
data2 = rec[key];
var xx = data2.replace("[", "").replace("]","").split(",");
data3.push(xx);
}
});
dataSource2 =
{
label: label,
backgroundColor: backgroundColor,
data: data3,
}
console.log("ds label " + JSON.stringify(label));
console.log("data3 " + JSON.stringify(data3));
data3 = [];
DS.push(dataSource2);
});
console.log("DS " + JSON.stringify(DS));
var tempData2 = {
labels: xLabelsArr,
datasets: DS,
};
var topTitle = { display: true, text: 'Maintenance Costs', fontStyle: 'bold', fontSize: 18, fontColor: 'white' };
var chart = new Chart(dynamicChartCanvas,
{
type: type,
data: tempData2,
options:
{
responsive: responsive,
title: topTitle,
legend: { position: 'bottom' },
}
});
The object array as logged:
DS [{"label":"Actual","backgroundColor":"#8e5ea2","data":[["408"," 547"," 675"," 534"]]},{"label":"Budgeted","backgroundColor":"red","data":[["350"," 447"," 725"," 534"]]}]
What was required, was a further iteration thru the JSON array in the data object, getting each value and building it into a js array.
if (key == "data")
{
var dataRec = rec[key];
var jsonData = JSON.parse(dataRec);
xValuesArray = [];
for (var i = 0; i < jsonData.length; i++)
{
var value = jsonData[i];
xValuesArray.push(value);
}
}
});
chartDataset =
{
label: label,
backgroundColor: backgroundColor,
data: xValuesArray,
}
chartDatasets.push(chartDataset);

How can I delete an instance of a chart using chart.js

My web page loads and automatically creates a chart with data it pulls from an API I wrote.
Ive also got a HTML input that allows me to select the month. I have added an event listener to that input that triggers a function to draw a new chart based on the month i have selected (it recalls the api too with these new parameters).
It looked like it worked, but on further inspection, I realised that the previous chart was behind the new chart.
Is there a way i can remove the old chart?
<div class="chart_div" style="max-height: 400px; max-width: 800px; margin: 5px">
<label for="monthSelector">Start month:</label>
<input
type="month"
id="monthSelector"
name="start"
min="{{min_date}}"
max="{{today_date}}"
value="{{today_date}}"
/>
<canvas id="myChart" width="400" height="400"> </canvas>
</div>
<script>
var canvas = document.getElementById("myChart");
const context = canvas.getContext("2d");
var monthSelector = document.getElementById("monthSelector");
// event listener for month slider
monthSelector.addEventListener("input", function () {
selected_date = monthSelector.value + "-01";
drawChart(selected_date);
});
var today = monthSelector.value + "-01";
// Draw chart upon loading page
drawChart(today);
function drawChart(date) {
x_labels = [];
data_set_scratches = [];
data_set_medical_scores = [];
context.clearRect(0, 0, canvas.width, canvas.height);
var url_scratches =
"http://127.0.0.1:8000/api/get-daily-scratch-count/" + date + "/";
var url_medical_scores =
"http://127.0.0.1:8000/api/get-daily-medical-score/" + date + "/";
// get x label based on dates of selected month
var date_vals = date.split("-");
var num_days = getDaysInMonth(date_vals[1], date_vals[0]);
console.log(num_days);
for (var i = 1; i <= num_days; i++) {
var num = minTwoDigits(i);
x_labels.push(num);
}
// call api to fetch the data
Promise.all([
fetch(url_scratches)
.then((res) => res.json())
.then(function (data) {
var scratches = data;
var dateIndex = 0;
var scratchesIndex = 0;
while (scratchesIndex < scratches.length) {
var scratchDates = scratches[scratchesIndex].date.split("-"); // Splits date into list ["YYYY", "MM", "DD"]
// if dates are equal, push total and increase both index
if (scratchDates[2] == x_labels[dateIndex]) {
data_set_scratches.push(scratches[scratchesIndex].total);
dateIndex += 1;
scratchesIndex += 1;
// if dates are not equal, push 0 and increase only date index
} else {
data_set_scratches.push(0);
dateIndex += 1;
}
}
console.log(data_set_scratches);
}),
fetch(url_medical_scores)
.then((res) => res.json())
.then(function (data) {
var medicalScores = data;
var dateIndex = 0;
var scoreIndex = 0;
while (scoreIndex < medicalScores.length) {
var scoreDates = medicalScores[scoreIndex].date.split("-"); // Splits date into list ["YYYY", "MM", "DD"]
// if dates are equal, push score then increase both index
if (scoreDates[2] == x_labels[dateIndex]) {
data_set_medical_scores.push(medicalScores[scoreIndex].score);
dateIndex += 1;
scoreIndex += 1;
// if dates are not equal, push 0 and increase only date index
} else {
data_set_medical_scores.push(0);
dateIndex += 1;
}
}
console.log(data_set_medical_scores);
}),
]).then(function () {
// Creat chart from api Data
let chartTest = new Chart(myChart, {
type: "line",
data: {
labels: x_labels,
datasets: [
{
label: "Scratch Total",
fill: false,
data: data_set_scratches,
borderColor: "green",
borderWidth: 1,
lineTension: 0,
backgroundColor: "red",
pointBackgroundColor: "red",
pointBorderColor: "red",
pointHoverBackgroundColor: "red",
pointHoverBorderColor: "red",
},
{
data: data_set_medical_scores,
label: "Medical Score",
fill: false,
borderColor: "orange",
borderWidth: 1,
lineTension: 0,
backgroundColor: "#e755ba",
pointBackgroundColor: "#55bae7",
pointBorderColor: "#55bae7",
pointHoverBackgroundColor: "#55bae7",
pointHoverBorderColor: "#55bae7",
},
],
},
options: {
title: {
display: true,
text: "Daily Scratches/Medical Scores",
},
scales: {
yAxes: [
{
ticks: {
beginAtZero: true,
},
},
],
xAxis: [
{
ticks: {
stepSize: 1,
autoSkip: false,
},
},
],
},
},
});
});
}
// function to get num of days in month
function getDaysInMonth(month, year) {
return new Date(year, month, 0).getDate();
}
function minTwoDigits(n) {
return (n < 10 ? "0" : "") + n;
}
</script>
What I would really like to do is delete the existing chart before the api is called again? Any help would be greatly appreciated.
call the destroy method of the chart object
.destroy()
Use this to destroy any chart instances that are created. This will clean up any references stored to the chart object within Chart.js, along with any associated event listeners attached by Chart.js. This must be called before the canvas is reused for a new chart.
// Destroys a specific chart instance
myLineChart.destroy();
https://www.chartjs.org/docs/latest/developers/api.html?h=destroy

How can I highlight a particular datapoint in chartjs, where my data is coming from json array?

// here I am taking another json encoded data from phpfile
$(document).ready(function () {
showGraph();
});
function showGraph()
{
{
$.post("phpfile.php",
function (data)
{
console.log(data);
var name = [];
var marks = [];
var height=[];
//and here as I couldn't encode two json array's separetly I'm declaring it to a variable and then using it
var jsonfile =[{"height":"85","st_name":"Name1"},{"height":"100","st_name":"Name3"},{"height":"92","st_name":"Name4"},{"height":"104","st_name":"Name5"},{"height":"91","st_name":"Name2"},{"height":"99","st_name":"Name6"},{"height":"140","st_name":"AI346"},{"height":"139","st_name":"abc"},{"height":"141","st_name":"def"},{"height":"140","st_name":"ghi"},{"height":"144","st_name":"jkl"},{"height":"130","st_name":"lmn"},{"height":"142","st_name":"opq"},{"height":"132","st_name":"rst"},{"height":"135","st_name":"xyz"},{"height":"135","st_name":"asdfsf"}];
//here I am reading the data from phpfile(1st Json array)
for (var i in data) {
name.push(data[i].st_name);
marks.push(data[i].height);
}
//here i am trying to access data from second json
for (var i=0;i<jsonfile.length;i++){
if(jsonfile[i].height==100)
{ height.push(jsonfile[i].height)}
}
//my graph function ,when I do this I am getting a single point with second json(height variable) but I need to highlight the particular point under a condition... I am not understanding how to do it.
var chartdata = {
labels: name,
datasets: [
{
label: 'height',
fill:false,
lineTension:0.5,
backgroundColor: '#5B2C6F',
borderColor: '#5B2C6F',
pointHoverBackgroundColor: '#5B2C6F',
pointHoverBorderColor: '#5B2C6F',
data: marks
//data:height
},
{
label: 'weight',
fill:false,
lineTension:0.1,
backgroundColor: '#C0392B',
borderColor: '#C0392B',
pointHoverBackgroundColor: '#C0392B',
pointHoverBorderColor: '#C0392B',
data:height,
//data:height
}
]
};
var graphTarget = $("#graphCanvas");
var lineGraph = new Chart(graphTarget, {
type: 'line',
data: chartdata,
options :{
scales:{
xAxes: [{
display: false //this will remove all the x-axis grid lines
}]
}
}
});
});
}
}
</script>
i will try to improve this.
var data =[{"height":"85","st_name":"Name1","color":"rgba(85, 85, 255, 255)"},{"height":"100","st_name":"Name3","color":"rgba(255, 0, 0, 2)"},{"height":"92","st_name":"Name4","color":"rgba(85, 85, 255, 255)"},{"height":"104","st_name":"Name5","color":"rgba(85, 85, 255, 255)"}];
var height = [];
var label = [];
var color = [];
for(i = 0; i<data.length; i++){
height.push(data[i]['height']);
label.push(data[i]['st_name']);
color.push(data[i]['color']);
}
var ctx = document.getElementById('myLine').getContext('2d');
var myLineChart = new Chart(ctx, {
type: 'line',
data: {
labels: label,
datasets: [{
data: height,
pointBorderColor: color,
}]
}
});

Categories