TypeError: CanvasRenderService is not a constructor - javascript

MY corona bot was working for a long time. it was offline for 3 months. Now, i have hosted it in vultr (hosting service). But i never faced this error, but facing this now....
New:
I just had a look, still i am having new error. MY code: https://paste.gg/p/anonymous/16c003ce7e49471b9fc7f4af25a688ae
Error is:
5|x | (node:19549) UnhandledPromiseRejectionWarning: Error: An options parameter object is required –
Yes i have moved from CanvasRenderService to ChartJSNodeCanvas
Old:
const { CanvasRenderSerice } = require("chartjs-node-canvas")
const canvasRenderService = new CanvasRenderService(
width,
height,
ChartJS => {}
);
With error:
5|x | (node:18303) UnhandledPromiseRejectionWarning: TypeError: CanvasRenderService is not a constructor
5|x | at Client.<anonymous> (/root/covid/bot.js:357:37)
5|x | at processTicksAndRejections (internal/process/task_queues.js:97:5)

They have renamed their service from CanvasRenderSerice in version 2.x.x to ChartJSNodeCanvas in version 3.x.x.
So you might be using version 3.x.x. Either downgrade your chartjs-node-canvas version 2.x.x or update your code according to new version.
2.x.x syntax
CanvasRenderService(width, height, chartCallback, type, chartJsFactory)
3.x.x
ChartJSNodeCanvas(options)
so in new version you've to use like
new ChartJSNodeCanvas({ width, height })
const { ChartJSNodeCanvas } = require('chartjs-node-canvas');
const chartCallback = (ChartJS) => {
// Global config example: https://www.chartjs.org/docs/latest/configuration/
ChartJS.defaults.global.elements.rectangle.borderWidth = 2;
};
const canvasRenderService = new ChartJSNodeCanvas({ width, height, chartCallback});
(async () => {
const configuration = {
type: "line",
data: {
labels: dates,
datasets: [
{
label: "Total Cases",
data: cases,
backgroundColor: "rgba(255,255,0,0.1)",
borderColor: "rgba(255,255,0,1)",
borderWidth: 2,
pointRadius: 2
},
{
label: "Recoveries",
data: recovered,
backgroundColor: "rgba(0,255,0,0.1)",
borderColor: "rgba(0,255,0,1)",
borderWidth: 2,
pointRadius: 2
},
{
label: "Deaths",
data: deaths,
backgroundColor: "rgba(255,0,0,0.1)",
borderColor: "rgba(255,0,0,1)",
borderWidth: 2,
pointRadius: 2
}
]
},
options: {
legend: {
position: "bottom",
labels: {
fontColor: "rgb(255, 255, 255,1)",
fontSize: 16
}
},
scales: {
xAxes: {
grid: {
display: false
},
ticks: {
fontColor: "rgba(255, 255, 255, 1"
}
},
yAxes: {
grid: {
lineWidth: 2,
color: "rgba(255, 255, 255, 0.8)"
},
ticks: {
fontColor: "rgba(255, 255, 255, 1"
}
}
}
}
};
})
const image = await canvasRenderService.renderToBuffer( configuration );

Related

How to add a title in Doughnut chart chart.js React

I want to add a Title for the Doughnut chart in my React app but for some reason it doesn't work. I have this code:
const chartData = {
labels: [],
datasets: [{
data: [],
backgroundColor: [
Colors.primary,
Colors.secondary,
Colors.danger,
Colors.warning
],
hoverBackgroundColor: [
'rgb(143, 0, 180, 0.3)',
'rgb(0, 196, 204, 0.3)',
'rgb(206, 0, 0, 0.3)',
'rgb(255, 179, 0, 0.3)'
],
hoverOffset: 10
}]
};
const options = {
responsive: true,
legend: {
display: false,
position: 'right',
},
title: {
display: true,
fontSize: 20,
text: 'Tickets'
}
}
<Doughnut
data = { chartData }
options = { options }
/>
What could have gone wrong here? I also want to place the labels on the right side of the chart, but it doesn't work as well. Below is the output.
Since Chart.js version 3 title, subtitle, legend and tooltip are plugins and their options must be defined in plugins node.
As far as I have seen, react-chartjs-2 is working with Chartjs version >= 3.
const options = {
responsive: true,
plugins: {
legend: {
display: false,
position: 'right',
},
title: {
display: true,
fontSize: 20, // <--- this is not a managed option since CHART.JS 3
text: 'Tickets'
}
}
}

options in Doughnut Chart error: Uncaught TypeError: Cannot read properties of undefined React

I use Doughnut chart form chart.js in React.
This code give me the error.
renderDoughnutChart(data, label) {
const chartData = {
labels: [],
datasets: [{
label: 'My First Dataset',
data: [],
backgroundColor: [
Colors.primary,
Colors.secondary,
Colors.danger,
Colors.warning
],
hoverBackgroundColor: [
'rgb(143, 0, 180, 0.3)',
'rgb(0, 196, 204, 0.3)',
'rgb(206, 0, 0, 0.3)',
'rgb(255, 179, 0, 0.3)'
],
hoverOffset: 30
}]
};
const options = {
responsive: true,
legend: {
display: false,
position: 'right',
},
title: {
display: true,
fontSize: 20,
text: 'My Title'
},
};
data.map((value) => {
if(value.value >= 0)
chartData.datasets[0].data.push(value.value)
else
chartData.datasets[0].data.push(0)
chartData.labels.push(value.label)
})
return (
<div style={{ width: '50%'}}>
<Doughnut
data = { chartData }
options = { options }
/>
</div>
)
}
Error:index.js:188 Uncaught TypeError: Cannot read properties of undefined (reading 'configMerge')
But if I don't pass the options = {options} to the Doughnut component, it works fine. What could cause the error?
Dependecy versions used:
chart.js: #3.3.0
react-chartjs-2: #2.9.0
Imports:
import { Chart } from "chart.js/auto"
import { Line, Doughnut } from 'react-chartjs-2'

Can anyone help me move data from an Axios JSON response to a plot points on a Chart js line chart?

I am working on building a React app that contains a line chart representing the timeline of data recordings from a certain point in time to present day. I am using the JS library Chart js. Specifically the 'react-chartjs-2' plugin. I am using the '/historical/all' path of the following API:
[https://corona.lmao.ninja/docs/?urls.primaryName=version%202.0.0#/][1]
I am successfully retrieving a response from the Axios GET request. But the structuring of the JSON being sent back to me is confusing me when it comes to the implementation I have been following to build the application. I have a lot of the scaffolding in place, but I am struggling to get the data from GET request function to the line chart.
The data is being sent in the following structure:
{
"cases": {
"3/21/20": 304507,
"3/22/20": 336953,
"3/23/20": 378231,
"3/24/20": 418041,
"3/25/20": 467653,
"3/26/20": 529591,
"3/27/20": 593291,
"3/28/20": 660693,
"3/29/20": 720140,
"3/30/20": 782389,
"3/31/20": 857487,
"4/1/20": 932605,
"4/2/20": 1013466,
"4/3/20": 1095917,
"4/4/20": 1176060,
"4/5/20": 1249754,
"4/6/20": 1321481,
"4/7/20": 1396476,
"4/8/20": 1480202,
"4/9/20": 1565278,
"4/10/20": 1657526,
"4/11/20": 1735650,
"4/12/20": 1834721,
"4/13/20": 1904838,
"4/14/20": 1976191,
"4/15/20": 2056054,
"4/16/20": 2152437,
"4/17/20": 2240190,
"4/18/20": 2317758,
"4/19/20": 2401378
},
"deaths": {
"3/21/20": 12973,
"3/22/20": 14651,
"3/23/20": 16505,
"3/24/20": 18625,
"3/25/20": 21181,
"3/26/20": 23970,
"3/27/20": 27198,
"3/28/20": 30652,
"3/29/20": 33925,
"3/30/20": 37582,
"3/31/20": 42107,
"4/1/20": 47180,
"4/2/20": 52983,
"4/3/20": 58787,
"4/4/20": 64606,
"4/5/20": 69374,
"4/6/20": 74565,
"4/7/20": 81937,
"4/8/20": 88338,
"4/9/20": 95521,
"4/10/20": 102525,
"4/11/20": 108502,
"4/12/20": 114090,
"4/13/20": 119481,
"4/14/20": 125983,
"4/15/20": 134176,
"4/16/20": 143800,
"4/17/20": 153821,
"4/18/20": 159509,
"4/19/20": 165043
},
"recovered": {
"3/21/20": 91682,
"3/22/20": 97889,
"3/23/20": 98341,
"3/24/20": 107890,
"3/25/20": 113604,
"3/26/20": 121966,
"3/27/20": 130659,
"3/28/20": 138949,
"3/29/20": 148616,
"3/30/20": 164100,
"3/31/20": 176442,
"4/1/20": 191853,
"4/2/20": 208528,
"4/3/20": 223621,
"4/4/20": 243575,
"4/5/20": 257000,
"4/6/20": 273259,
"4/7/20": 296263,
"4/8/20": 324507,
"4/9/20": 348813,
"4/10/20": 370241,
"4/11/20": 395521,
"4/12/20": 414599,
"4/13/20": 440897,
"4/14/20": 466051,
"4/15/20": 502053,
"4/16/20": 532409,
"4/17/20": 557798,
"4/18/20": 581355,
"4/19/20": 612056
}
}
I would like for each category (cases, deaths, recovered) to represent a line on the chart showing the progression over time, but I'm unsure how to handle it. With the intention being that the dates would be the X-axis and the points would be plotted in a different colored line for each.
Would anyone be able to help with this at all? I would greatly appreciate some guidance. Below are the two primary files corresponding to the Chart and API handling:
index.js
export const fetchDailyData = async () => {
try {
const { data } = await axios.get(`${url}/historical/all`);
const labels = Object.keys(data.cases);
const cases = labels.map((name) => data.cases[name]);
const deaths = labels.map((name) => data.deaths[name]);
const recovered = labels.map((name) => data.recovered[name]);
return {labels, cases, deaths, recovered};
} catch (error) {
return error;
}
}
Chart.jsx
import React, { useState, useEffect } from 'react';
import { Line, Bar } from 'react-chartjs-2';
import { fetchDailyData } from '../../api';
import styles from './Chart.module.css';
const Chart = ({data: { labels, cases, deaths, recovered }}) => {
const [dailyData, setDailyData] = useState([]);
useEffect(() => {
const fetchAPI = async () => {
setDailyData(await fetchDailyData());
}
fetchAPI();
}, []);
const lineChart = (
<Line data = {
{
labels,
datasets: [{
data:cases,
label: 'Infected',
borderColor: '#3333ff',
fill: true,
}, {
data: deaths,
label: 'Deaths',
borderColor: 'red',
backgroundColor: 'rgba(255, 0, 0, 0.5)',
fill: true,
},
{
data: recovered,
label: 'Recovered',
borderColor: 'green',
backgroundColor: 'rgba(0, 255, 0, 0.5)',
fill: true,
}],
}
}
/>
);
return (
<div className = { styles.container }>
{lineChart}
</div>
);
};
export default Chart;
Here is a complete solution:
// Create the chartData state
const [chartData, setChartData] = useState();
// in your fetch function, convert the data to chartData
const labels = Object.keys(data.cases);
const cases = labels.map((name) => data.cases[name]);
const deaths = labels.map((name) => data.deaths[name]);
const recovered = labels.map((name) => data.recovered[name]);
setChartData({
labels,
datasets: [{
data: cases,
label: 'Infected',
borderColor: '#3333ff',
fill: true
}, {
data: deaths,
label: 'Deaths',
borderColor: 'red',
backgroundColor: 'rgba(255, 0, 0, 0.5)',
fill: true
}, {
data: recovered,
label: 'Recovered',
borderColor: 'green',
backgroundColor: 'rgba(0, 255, 0, 0.5)',
fill: true
}]
})
// Now render your chart (but make sure chartData exists)
return (
<div className = { styles.container }>
{chartData &&
<Line data={chartData} />
}
</div>
);
First extract the x labels:
const labels = Object.keys(dailyData.cases);
Then extract the y values for each serie:
const cases = Object.keys(dailyData.cases).map((name) => dailyData.cases[name]);
const deaths = Object.keys(dailyData.deaths).map((name) => dailyData.deaths[name]);
const recovered = Object.keys(dailyData.recovered).map((name) => dailyData.recovered[name]);
Then assemble everything into a chart js object:
<Line data = {
labels,
datasets: [{
data: cases,
label: 'Infected',
borderColor: '#3333ff',
fill: true
}, {
data: deaths,
label: 'Deaths',
borderColor: 'red',
backgroundColor: 'rgba(255, 0, 0, 0.5)',
fill: true
}, {
data: recovered,
label: 'Recovered',
borderColor: 'green',
backgroundColor: 'rgba(0, 255, 0, 0.5)',
fill: true
}]
}
/>

Update ChartJs chart using $scope in AngularJS

I'm having some issues when trying to update a chart's data using $scope.
I know there's a function to update charts myChart.update(); but I can't get to update the char when I put it in a $scope.
The following code gets the chart's data and then tries to update the chart. The problem comes at $scope.lineChart.update();. It looks like chartjs can't detect any changes.
The following code is executed after triggering a select, so the chart has an initial data and the following code just tries to update it.
This does not work: $scope.lineChart.update();
$scope.getLineChartMaxData().then(function () {
$scope.getLineChartMinData().then(function () {
$scope.lineChart.update();
});
});
The chart function:
$scope.fillLineChart = function () {
console.log("FILLING LINE CHART");
const brandProduct = 'rgba(0,181,233,0.5)'
const brandService = 'rgba(0,173,95,0.5)'
var data1 = $scope.lineChartMaxWeekData;
var data2 = $scope.lineChartMinWeekData;
var maxValue1 = Math.max.apply(null, data1)
var maxValue2 = Math.max.apply(null, data2)
var minValue1 = Math.min.apply(null, data1)
var minValue2 = Math.min.apply(null, data2)
var maxValue;
var minValue;
if (maxValue1 >= maxValue2) {
maxValue = maxValue1;
} else {
maxValue = maxValue2;
}
if (minValue1 >= minValue2) {
minValue = minValue2;
} else {
minValue = minValue1;
}
$scope.minValue = minValue;
$scope.maxValue = maxValue;
var ctx = document.getElementById("recent-rep-chart");
if (ctx) {
ctx.height = 250;
$scope.lineChart = new Chart(ctx, {
type: 'line',
data: {
labels: $scope.lineChartMaxWeekLabels,
datasets: [{
label: 'Valor',
backgroundColor: brandService,
borderColor: 'transparent',
pointHoverBackgroundColor: '#fff',
borderWidth: 0,
data: data1
},
{
label: 'My Second dataset',
backgroundColor: brandProduct,
borderColor: 'transparent',
pointHoverBackgroundColor: '#fff',
borderWidth: 0,
data: data2
}
]
},
options: {
maintainAspectRatio: true,
legend: {
display: false
},
responsive: true,
scales: {
xAxes: [{
gridLines: {
drawOnChartArea: true,
color: '#f2f2f2'
},
ticks: {
fontFamily: "Poppins",
fontSize: 12
}
}],
yAxes: [{
ticks: {
beginAtZero: true,
maxTicksLimit: 5,
stepSize: 50,
max: maxValue,
fontFamily: "Poppins",
fontSize: 12
},
gridLines: {
display: true,
color: '#f2f2f2'
}
}]
},
elements: {
point: {
radius: 0,
hitRadius: 10,
hoverRadius: 4,
hoverBorderWidth: 3
}
}
}
});
}
};
UPDATE: $scope.lineChart.destroy(); works well, but I don't want to destroy the chart and build it again because it is built with another sizes.

How to use JSON data in creating a chart with chartjs?

In my controller I have an Action method that will find all questions in a table called Questions, and the answers for each question.
This Action is of type ContentResult that will return a result serialized in Json format.
public ContentResult GetData()
{
var datalistQuestions = db.Questions.ToList();
List<PsychTestViewModel> questionlist = new List<PsychTestViewModel>();
List<PsychTestViewModel> questionanswerslist = new List<PsychTestViewModel>();
PsychTestViewModel ptvmodel = new PsychTestViewModel();
foreach (var question in datalistQuestions)
{
PsychTestViewModel ptvm = new PsychTestViewModel();
ptvm.QuestionID = question.QuestionID;
ptvm.Question = question.Question;
questionlist.Add(ptvm);
ViewBag.questionlist = questionlist;
var agree = //query
var somewhatAgree = //query
var disagree = //query
int Agree = agree.Count();
int SomewhatAgree = somewhatAgree.Count();
int Disagree = disagree.Count();
ptvmodel.countAgree = Agree;
ptvmodel.countSomewhatAgree = SomewhatAgree;
ptvmodel.countDisagree = Disagree;
questionanswerslist.Add(ptvmodel);
ViewBag.questionanswerslist = questionanswerslist;
}
return Content(JsonConvert.SerializeObject(ptvmodel), "application/json");
}
Now, my problem is the pie chart is not being created and I don't quite know how to push the values to my data structure?
What should I be doing instead?
Here is my script:
#section Scripts {
<script type="text/javascript">
var PieChartData = {
labels: [],
datasets: [
{
label: "Agree",
backgroundColor:"#f990a7",
borderWidth: 2,
data: []
},
{
label: "Somewhat Agree",
backgroundColor: "#aad2ed",
borderWidth: 2,
data: []
},
{
label: "Disgree",
backgroundColor: "#9966FF",
borderWidth: 2,
data: []
},
]
};
$.getJSON("/PsychTest/GetData/", function (data) {
for (var i = 0; i <= data.length - 1; i++) {
PieChartData.datasets[0].data.push(data[i].countAgree);
PieChartData.datasets[1].data.push(data[i].countSomewhatAgree);
PieChartData.datasets[2].data.push(data[i].countDisagree);
}
var ctx = document.getElementById("pie-chart").getContext("2d");
var myLineChart = new Chart(ctx,
{
type: 'pie',
data: PieChartData,
options:
{
responsive: true,
maintainaspectratio: true,
legend:
{
position : 'right'
}
}
});
});
</script>
You need two arrays for creating your chart. One of them indicates titles and another one shows the number of each titles. You have titles in the client side, so you only need the number of each options and it could be fetched from a simple server method like:
[HttpGet]
public JsonResult Chart()
{
var data = new int[] { 4, 2, 5 }; // fill it up whatever you want, but the number of items should be equal with your options
return JsonConvert.SerializeObject(data)
}
The client side code is here:
var aLabels = ["Agree","Somewhat Agree","Disagree"];
var aDatasets1 = [4,2,5]; //fetch these from the server
var dataT = {
labels: aLabels,
datasets: [{
label: "Test Data",
data: aDatasets1,
fill: false,
backgroundColor: ["rgba(54, 162, 235, 0.2)", "rgba(255, 99, 132, 0.2)", "rgba(255, 159, 64, 0.2)", "rgba(255, 205, 86, 0.2)", "rgba(75, 192, 192, 0.2)", "rgba(153, 102, 255, 0.2)", "rgba(201, 203, 207, 0.2)"],
borderColor: ["rgb(54, 162, 235)", "rgb(255, 99, 132)", "rgb(255, 159, 64)", "rgb(255, 205, 86)", "rgb(75, 192, 192)", "rgb(153, 102, 255)", "rgb(201, 203, 207)"],
borderWidth: 1
}]
};
var opt = {
responsive: true,
title: { display: true, text: 'TEST CHART' },
legend: { position: 'bottom' },
//scales: {
// xAxes: [{ gridLines: { display: false }, display: true, scaleLabel: { display: false, labelString: '' } }],
// yAxes: [{ gridLines: { display: false }, display: true, scaleLabel: { display: false, labelString: '' }, ticks: { stepSize: 50, beginAtZero: true } }]
//}
};
var ctx = document.getElementById("myChart").getContext("2d");
var myNewChart = new Chart(ctx, {
type: 'pie',
data: dataT,
options: opt
});
<script src="https://github.com/chartjs/Chart.js/releases/download/v2.7.1/Chart.min.js"></script>
<div Style="font-family: Corbel; font-size: small ;text-align:center " class="row">
<div style="width:100%;height:100%">
<canvas id="myChart" style="padding: 0;margin: auto;display: block; "> </canvas>
</div>
</div>
If you are still looking to use json for chart.js charts.
Here is a solution which fetch a json file and render it on chart.js chart.
fetch('https://s3-us-west-2.amazonaws.com/s.cdpn.io/827672/CSVtoJSON.json')
.then(function(response) {
return response.json();
})
.then(function(ids) {
new Chart(document.getElementById("bar-chart"), {
type: 'bar',
data: {
labels: ids.map(function(id) {
return id.Label;
}),
datasets: [
{
label: "value2",
backgroundColor: ["#3e95cd", "#8e5ea2","#3cba9f","#e8c3b9","#c45850"],
data: ids.map(function(id) {
return id.Value2;
}),
},
{
label: "value",
//backgroundColor: ["#3e95cd", "#8e5ea2","#3cba9f","#e8c3b9","#c45850"],
data: ids.map(function(id) {
return id.Value;
}),
},
]
},
options: {
legend: { display: false },
title: {
display: true,
text: 'Sample Json Data Chart'
}
}
});
});
see running code on jsfiddle here

Categories