how to Show value in pie chart Legend in react-chartjs-2 - javascript

I'm using react-Chartjs-2 pie chart for my dashboard. as per the requirement I have to show both label with data in the legend. the below component which I'm using in my application
import React, { Component } from "react";
import { Doughnut } from "react-chartjs-2";
class DoughnutChart extends Component {
constructor(props) {
super(props);
}
render() {
const chartdata = {
labels: ["Newly Added", "Edited", "Deleted"],
datasets: [
{
label: "Markets Monitored",
backgroundColor: [
"#83ce83",
"#959595",
"#f96a5d",
"#00A6B4",
"#6800B4",
],
data: [9, 5, 3],
},
],
};
return (
<Doughnut
data={chartdata}
options={{
legend: { display: true, position: "right" },
datalabels: {
display: true,
color: "white",
},
tooltips: {
backgroundColor: "#5a6e7f",
},
}}
/>
);
}
}
export default DoughnutChart;
now I'm getting chart like given below
my output
my requirement is adding values in legend(customizing chart legend). example image expected output

One way to do it would be to define data and labels before creating the chart. Then you can add the data to labels using .map method.
import React, { Component } from "react";
import { Doughnut } from "react-chartjs-2";
class DoughnutChart extends Component {
constructor(props) {
super(props);
}
render() {
let data = [9, 5, 3]
let labels = ["Newly Added", "Edited", "Deleted"]
let customLabels = labels.map((label,index) =>`${label}: ${data[index]}`)
const chartdata = {
labels: customLabels,
datasets: [
{
label: "Markets Monitored",
backgroundColor: [
"#83ce83",
"#959595",
"#f96a5d",
"#00A6B4",
"#6800B4",
],
data: data,
},
],
};
return (
<Doughnut
data={chartdata}
options={{
legend: { display: true, position: "right" },
datalabels: {
display: true,
color: "white",
},
tooltips: {
backgroundColor: "#5a6e7f",
},
}}
/>
);
}
}
export default DoughnutChart;

Related

Chart.js legend configuration options not working [duplicate]

I am trying to hide the legend of my chart created with Chart.js.
According to the official documentation (https://www.chartjs.org/docs/latest/configuration/legend.html), to hide the legend, the display property of the options.display object must be set to false.
I have tried to do it in the following way:
const options = {
legend: {
display: false,
}
};
But it doesn't work, my legend is still there. I even tried this other way, but unfortunately, without success.
const options = {
legend: {
display: false,
labels: {
display: false
}
}
}
};
This is my full code.
import React, { useEffect, useState } from 'react';
import { Line } from "react-chartjs-2";
import numeral from 'numeral';
const options = {
legend: {
display: false,
},
elements: {
point: {
radius: 1,
},
},
maintainAspectRatio: false,
tooltips: {
mode: "index",
intersect: false,
callbacks: {
label: function (tooltipItem, data) {
return numeral(tooltipItem.value).format("+0,000");
},
},
},
scales: {
xAxes: [
{
type: "time",
time: {
format: "DD/MM/YY",
tooltipFormat: "ll",
},
},
],
yAxes: [
{
gridLines: {
display: false,
},
ticks: {
callback: function(value, index, values) {
return numeral(value).format("0a");
},
},
},
],
},
};
const buildChartData = (data, casesType = "cases") => {
let chartData = [];
let lastDataPoint;
for(let date in data.cases) {
if (lastDataPoint) {
let newDataPoint = {
x: date,
y: data[casesType][date] - lastDataPoint
}
chartData.push(newDataPoint);
}
lastDataPoint = data[casesType][date];
}
return chartData;
};
function LineGraph({ casesType }) {
const [data, setData] = useState({});
useEffect(() => {
const fetchData = async() => {
await fetch("https://disease.sh/v3/covid-19/historical/all?lastdays=120")
.then ((response) => {
return response.json();
})
.then((data) => {
let chartData = buildChartData(data, casesType);
setData(chartData);
});
};
fetchData();
}, [casesType]);
return (
<div>
{data?.length > 0 && (
<Line
data={{
datasets: [
{
backgroundColor: "rgba(204, 16, 52, 0.5)",
borderColor: "#CC1034",
data: data
},
],
}}
options={options}
/>
)}
</div>
);
}
export default LineGraph;
Could someone help me? Thank you in advance!
PD: Maybe is useful to try to find a solution, but I get 'undefined' in the text of my legend and when I try to change the text like this, the text legend still appearing as 'Undefindex'.
const options = {
legend: {
display: true,
text: 'Hello!'
}
};
As described in the documentation you linked the namespace where the legend is configured is: options.plugins.legend, if you put it there it will work:
var options = {
type: 'line',
data: {
labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"],
datasets: [{
label: '# of Votes',
data: [12, 19, 3, 5, 2, 3],
borderColor: 'pink'
}
]
},
options: {
plugins: {
legend: {
display: false
}
}
}
}
var ctx = document.getElementById('chartJSContainer').getContext('2d');
new Chart(ctx, options);
<body>
<canvas id="chartJSContainer" width="600" height="400"></canvas>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.5.0/chart.js"></script>
</body>
On another note, a big part of your options object is wrong, its in V2 syntax while you are using v3, please take a look at the migration guide
Reason why you get undefined as text in your legend is, is because you dont supply any label argument in your dataset.
in the newest versions this code works fine
const options = {
plugins: {
legend: {
display: false,
},
},
};
return <Doughnut data={data} options={options} />;
Import your options value inside the charts component like so:
const options = {
legend: {
display: false
}
};
<Line data={data} options={options} />

Cannot read property 'length' of undefined for ChartJS when I use it inside React

I have built a custom component for Radar Chart:
class RadarChart extends Component {
constructor(props) {
super(props);
this.canvasRef = React.createRef;
}
componentDidMount () {
console.log('props: ', this.props)
this.myRadarChart = new Chart(this.canvasRef.current, {
type: 'radar',
data: {
labels: this.props.labels,
datasets: [
{
label: "My Second dataset",
backgroundColor: "rgba(26,179,148,0.2)",
borderColor: "rgba(26,179,148,1)",
pointBackgroundColor: "rgba(26,179,148,1)",
pointBorderColor: "rgba(26,179,148,1)",
data: this.props.data
}
]
},
options: {
responsive: true,
legend: {
display: false
}
}
})
}
render() {
return <canvas ref={this.chartRef} />
}
}
I reference the above component and into my other component and pass as props both the data and labels like this.
class Name1 extends Component {
state = {
data: [28, 48, 40, 19],
labels: ["In Person Call", "RTE", "MobilePush", "Speaker Program"],
};
render() {
return (
<div>
<RadarChart
data={this.state.data}
labels={this.state.labels}
/>
</div>
)
}
But I get this error: TypeError: Cannot read property 'length' of undefined.
I checked in the console and I'm able to pass on the data and labels to the other component but for some reason I see that error. Any suggestions?
Modified my code to this and got the chart displayed. I don't know what the issue was but it could be that I hadn't added getContext. I also created the ref outside my state.
class RadarChart extends Component {
constructor(props) {
super(props);
}
chartRef = React.createRef();
componentDidMount () {
const myChartRef = this.chartRef.current.getContext("2d");
new Chart(myChartRef, {
type: 'radar',
data: {
labels: this.props.labels,
datasets: [
{
label: "My Second dataset",
backgroundColor: "rgba(26,179,148,0.2)",
borderColor: "rgba(26,179,148,1)",
pointBackgroundColor: "rgba(26,179,148,1)",
pointBorderColor: "rgba(26,179,148,1)",
data: this.props.data
}
]
},
options: {
responsive: true,
legend: {
display: false
}
}
})
}
render() {
return <canvas ref={this.chartRef} />
}
}

chart.js auto-panning when new data added to graph

I am using chart.js in a React app to chart live data. I want the user to be able to pan and zoom on the graph, so I've also included the chart.js zoom plugin. My relevant code is below. Before I've either zoomed or panned, the chart continually shifts to show new data. However, after zooming of panning, the chart no longer automatically shifts to show new data—I need to manually zoom out or pan right to show the new data. I'd like it to be so that if the user is zoomed/panned on the far right side of the chart (i.e., where the newest data is added), the chart will automatically shift as it does before I initially zoom/pan. Is this possible? Or is there another way I can go about doing this if it does not work with chart.js? Thanks!
// graph.js
import React from "react";
import Chart from "./chart";
import * as zoom from 'chartjs-plugin-zoom';
let updateInterval = 1000;
let typeData = "Live";
class Graph extends React.Component {
constructor(props) {
super(props);
this.state = {
meta: {
ticks: props.ticks,
lab: [],
dat: []
},
lineChartData: {
labels: [],
datasets: [
{
type: "line",
label: typeData,
backgroundColor: "rgba(0, 0, 0, 0)",
borderColor: this.props.theme.palette.primary.main,
pointBackgroundColor: this.props.theme.palette.secondary.main,
pointBorderColor: this.props.theme.palette.secondary.main,
borderWidth: "2",
lineTension: 0.45,
data: []
}
]
},
lineChartOptions: {
responsive: true,
maintainAspectRatio: false,
tooltips: {
enabled: true
},
scales: {
xAxes: [
{
ticks: {
autoSkip: true,
suggestedMax: 100
}
}
]
},
plugins: {
zoom: {
pan: {
enabled: true,
mode: 'x',
speed: 100,
},
zoom: {
enabled: true,
mode: 'x',
speed: 0.75,
}
}
}
}
};
this.updateChart = this.updateChart.bind(this);
}
componentDidMount() {
setInterval( this.updateChart,
updateInterval)
}
updateChart() {
console.log(this.state.lineChartOptions.scales.xAxes.suggestedMax);
const newDat = this.state.meta.dat;
const newNum = Math.round(Math.random()*100);
newDat.push(newNum);
const newLab = [...Array(newDat.length).keys()];
const newMeta = {ticks: this.props.ticks, lab: newLab, dat: newDat}
this.setState({meta: newMeta})
const oldDataSet = this.state.lineChartData.datasets[0];
let newDataSet = { ...oldDataSet };
newDataSet.data.push(newNum);
const possLabs = this.state.meta.lab;
const newChartData = {
...this.state.lineChartData,
datasets: [newDataSet],
labels: possLabs
};
this.setState({ lineChartData: newChartData });
}
render() {
return (
<div style={{height: 400}}>
<Chart
data={this.state.lineChartData}
options={this.state.lineChartOptions}
/>
</div>
);
}
}
export default Graph;
// chart.js
import React from "react";
import { Line } from "react-chartjs-2";
const Chart = props => <Line data={props.data} options={props.options} />;
export default Chart;
// App.js
import React from "react";
import Graph from "./graph"
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
}
};
render() {
return (
<div>
<Graph/>
</div>
);
}
}
export default App;

Two different x axis labels on line chart, chart.js react

I'm trying to create a chart component for weather in React using chart.js. I want two different x axis with the temp above the chart, and the times below the chart. The data is correct in how I wan't it, I just want to use two different labels along the top and the bottom of the x axis.
How would I do this?
import React from "react";
import { Line } from 'react-chartjs-2';
class WeatherOverview extends React.Component {
constructor(props){
super(props);
this.state = {
chartData: {
labels: ['15:00', '18:00', '21:00', '00:00', '03:00', '06:00', '09:00', '12:00'], //time
datasets: [{
data: [18, 19, 18, 16, 15, 15, 16, 17, 18] //temp
}],
}
}
}
render(){
return (
<div className="chart">
<Line
data={this.state.chartData}
options={{
scales: {
yAxes: [{
gridLines: {
drawOnChartArea: false
},
ticks: {
suggestedMin: 13, // lowest from data minus 2/3
display: false
}
}],
xAxes: [
{
gridLines: {
drawOnChartArea: false
},
},
{ position: 'top' },
]
}
}}
/>
</div>
)
}
}
export default WeatherOverview;
look at this ref her:
How to create two x-axes label using chart.js
it looks like what you are asking about.
enjoy!

Vertical stacking of line plots using ChartJs library sharing same x axis

I want to have three LineCharts below each other. They are sharing same x-axis (time). I was able to create this:
However, it is very useless to have x-axis on the top and middle chart. I would prefer not to display the x-axis for the top and middle. When I tried it, I got this:
But as you can see, the last grid for 12AM is not visible for the top and middle chart, and the grids are not aligned (it looks weird). Each chart is rendered as a separate component using React.
Here are my TimelinePlot component which is rendering each LineChart (sorry for the mess, but I did not yet refactor it):
import React from 'react';
import { Line } from 'react-chartjs-2';
import { GetColors } from '../../utils/PlotDescriptionHelper';
class TimelinePlot extends React.Component {
MapPropsToData(props) {
const colors = GetColors(props.series.length);
return props.series.map((dataset, index) => {
return {
label: dataset.name,
data: dataset.data,
borderWidth: 1,
fill: false,
borderColor: colors[index],
//pointBackgroundColor: 'rgb(255,255,255)',
};
});
}
MapPropsToOptions(props) {
return {
elements: {
point: {
radius: 0,
},
},
legend: {
// display: props.showLegend,
position: 'top',
align: 'end',
},
scales: {
yAxes: [
{
ticks: props.yAxisTicks,
scaleLabel: {
display: true,
labelString: props.yAxisName + props.yAxisUnit,
},
},
],
xAxes: [
{
type: 'time',
// position: props.xAxisPosition,
time: {
parser: 'YYYY-MM-DD HH:mm',
tooltipFormat: 'll HH:mm',
},
// scaleLabel: {
// display: true,
// //labelString: 'Date',
// },
ticks: {
min: props.xAxisStart,
max: props.xAxisEnd,
//display: true,
display: props.xAxisDisplay,
},
},
],
},
};
}
render() {
const dataset = { datasets: this.MapPropsToData(this.props) };
return (
<div className='measurement-row'>
<Line
data={dataset}
options={this.MapPropsToOptions(this.props)}
position='absolute'
height='15%'
width='80%'
/>
</div>
);
}
}
And here is the render method of the parent using TimelinePlot component:
render() {
var plots = Object.keys(this.state.timeSeries).map((key, index) => {
return (
<TimelinePlot
key={key + index}
series={this.state.timeSeries[key]}
yAxisName={FirstLetterToUpper(key)}
yAxisUnit={MapKeyToUnit(key)}
xAxisDisplay={index === Object.keys(this.state.timeSeries).length - 1}
xAxisPosition={index === 0 ? 'top' : 'bottom'}
xAxisStart={this.state.startTime}
xAxisEnd={this.state.endTime}
showLegend={index === 0}
yAxisTicks={MapYAxisTicks(key)}
/>
);
});
return (
<div className='width-90'>
<TimelineDashboardHeader />
<div className='dashboard__column'>{plots}</div>
</div>
);
}

Categories