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

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'

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'
}
}
}

How to create a bar and a line in a same graph using chart.js in React?

(Requirement: The bar has to start from the first tick(i.e label "a" below) in x axis whereas the line has to start from third tick(label "c" below)).
I have tried the following way.
import React from "react";
import Chart from 'chart.js';
import ChartDataLabels from 'chartjs-plugin-datalabels';
class Barchart extends React.Component {
//chart= null;
componentDidMount(){
this.configureChart();
}
configureChart = ()=>{
let bardata=[7, 3, 2];
let linedata=[ 0,0,0,75, 55, 80, 65];
// xaxislabel=["a","b","c"]
// xaxislabelline=["d","e","f","g"]
const node=this.node;
new Chart(node,{
plugins: [ChartDataLabels],
type:'',
data:{
datasets:[
{
yAxisID:'A',
label: "Bar Dataset",
data: bardata ,
type: "bar",
backgroundColor: "#DE924B",
order:1
},
{
yAxisID:'B',
label: "Line Dataset 2",
data: linedata,
type: "line",
fill: false,
borderColor: 'rgb(75, 192, 192)',
order:2
},
],
labels:["a","b","c","d","e","f","g"]
},
options:{
scales:{
yAxes:[
{ id:'A',
display:true,
ticks:{
beginAtZero:true
}
},
{ id:'B',
display:true,
ticks:{
beginAtZero:true
}
}
],
xAxes:[
{ id:'C',
display: true,
barThickness: 25,
ticks: {
beginAtZero: true,
}
},
{ id:'D',
display: true,
ticks: {
beginAtZero:true,
min:'c',
}
}
},
]
}
}
})
}
render(){
return(
<div>
<canvas
style={{ width: 650, height: 165 }}
ref={node => (this.node = node)}
/>
</div>
);
}
}
export default Barchart;
Below is the attached result I got.
I am not sure how to have the line graph start from label "c" of the main label(or have single label for both graphs).
Found the solution.
changed
let linedata=[ 0,0,0,75, 55, 80, 65]-->
let linedata=[ null,null,null,75, 55, 80, 65];

TypeError: CanvasRenderService is not a constructor

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 );

add a unit to label with chartjs plugin datalabels

I am opening a new question following Rohit's answer on this question Chart.js Show labels on Pie chart
Is it possible to modify the labels with the plugin chartjs datalabels, for exemple add a unit to it?
Thanks for your answer!
EDIT:
Following Ty answer, I tried this:
if(type==='pie'){
GraphOpt['plugins'] = {
datalabels: {
formatter: (item) => {
return item + ' ' + label_unit;
}
}
}
}
else{
GraphOpt['tooltips'] = {
callbacks: {
label: (item) => `${item.yLabel} ${label_unit}`,
}
}
}
but it's still not showing the units on the graph.
Also, I can't get rid of the values showing on bar graphes with the plugin
EDIT2: My graph function
function setChart(Graph, ctx, type, graph_data, labels, title, label_graph, label_unit){
var GraphOpt = {
scales: {
yAxes: [{
ticks: {
beginAtZero: true
}
}]
},
title: {
display:true,
text: title,
},
tooltips: {},
plugins : {}
}
//graph config
var Graph_config = {
type: type,
data: {
labels: labels,
datasets: [{
label: label_graph,
data: graph_data,
backgroundColor: backgroundColor,
borderColor: backgroundColor,
borderWidth: 1
}]
},
options: GraphOpt,
}
if(type==='pie'){
GraphOpt['plugins'] = {
datalabels: {
formatter: (item) => {
return item + ' ' + label_unit;
}
}
}
}
else{
GraphOpt['tooltips'] = {
callbacks: {
label: (item) => `${item.yLabel} ${label_unit}`,
}
}
}
//create a new graph if graph doesn't exist (init)
console.log(typeof window[Graph])
if(typeof window[Graph] === "undefined") {
window[Graph] = new Chart(ctx, Graph_config);
console.log(typeof window[Graph])
//update if graph exist
}else{
console.log('Graph Update')
//updating with new chart data
window[Graph].config=Graph_config;
window[Graph].title=title;
//redraw the chart
window[Graph].update();
}
}
Yes, have a look at the chartjs-plugin-datalabels documentation. In particular, you want to use the options.plugins.datalabels.formatter option to specify a custom function and append units to every label string.
Here's an example Chart.js config that adds a unit to every data label:
{
type: 'pie',
data: {
datasets: [
{
data: [84, 28, 57, 97],
backgroundColor: [
'rgb(255, 99, 132)',
'rgb(255, 159, 64)',
'rgb(255, 205, 86)',
'rgb(75, 192, 192)',
],
label: 'Dataset 1',
},
],
labels: ['Red', 'Orange', 'Yellow', 'Green'],
},
options: {
plugins: {
datalabels: {
formatter: (val) => {
return val + ' kg';
}
}
}
}
}

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