I have created the SPFx React project.
I have implemented a bar chart using PrimeReact charts.
To my knowledge, PrimeReact uses the ChartJs library on the back end.
I need to add a label and value mark in red and blue to the image below.
Below is my code snippet,
import { Chart } from 'primereact';
import { Chart as ChartJS, ArcElement, Tooltip, Legend } from "chart.js";
ChartJS.register(ArcElement, Tooltip, Legend, ChartDataLabels);
<Chart type="bar" data={barChartData} options={barChartOptions} />
const barChartData = {
labels: ["Excellent", "Very Good", "Good", "Average"],
datasets: [
{
label: "Count",
data: [40, 50, 30, 10],
backgroundColor: ["#E74C3C", "#3498DB", "#F1C40F", "#27AE60"],
borderColor: ["#E74C3C", "#3498DB", "#F1C40F", "#27AE60"],
borderWidth: 1,
borderRadius: 10, // Rounded bar edges
barPercentage: 0.5,
barThickness: 6,
maxBarThickness: 8,
}
],
};
const barChartOptions = {
indexAxis: "y", // Horizontal chart
scales: {
x: {
beginAtZero: true,
ticks: {
display: false,
},
grid: {
display: false,
drawBorder: false
}
},
y: {
beginAtZero: true,
grid: {
display: false,
drawBorder: false
}
}
},
plugins: {
datalabels: {
color: '#000',
anchor: 'end',
align: 'end',
font: {
weight: 'bold',
}
},
tooltip: {
callbacks: {
label: function (context) {
const dataset = context.dataset;
const total = dataset.data.reduce((a, b) => a + b, 0); // Sum of all data
const value = dataset.data[context.dataIndex]; // Current value
const percentage = ((value / total) * 100).toFixed(2); // Calculate percentage
// return `${context.label}: ${percentage}%`; // Display label and percentage
return [`${context.label}: ${value} (${percentage}%)`]; // Display label and percentage
}
}
},
legend: {
display: false, // Hide the legend
},
},
layout: {
padding: {
right: 20, // Add padding to the top
},
},
responsive: true,
maintainAspectRatio: false,
animation: { duration: 0 }
};
Can anyone help me with the same?
Thanks in Advance.
The labels on the left can be set through barChartData.labels
:
const labels = [...barChartData.labels];
barChartData.labels = barChartData.datasets[0].data.map(v => `${v}%`);
This implies changing the original code in a few places to use the "global"
variable labels
as the source for original labels.
The tooltip options will require some changes:
tooltip: {
callbacks: {
title: function(context){
return labels[context[0].dataIndex];
},
label: function (context) {
const dataset = context.dataset;
const total = dataset.data.reduce((a, b) => a + b, 0); // Sum of all data
const value = dataset.data[context.dataIndex]; // Current value
const percentage = ((value / total) * 100).toFixed(2); // Calculate percentage
return [`${labels[context.dataIndex]}: ${value} (${percentage}%)`]; // Display label and percentage
}
}
}
For the labels on top of the bars, one can use (or should I say
hijack) the plugin chartjs-plugin-datalabels
that, by looking at the original code, seems to be already available.
The plugin options for those labels could be:
datalabels: {
color: '#777',
anchor: 'start',
align: 315,
offset: -4,
formatter: function(value, context) {
return labels[context.dataIndex]
},
font: {
weight: 'bold',
}
},
The full code in a stackblitz, forked from PrimeReact playground.
An alternative solution, if one doesn't want to mess with the labels in the original data, is to hide the y axis and show the left values as another data label, so the datalabels options would be:
datalabels: {
labels: {
left:{
anchor: 'start',
align: 205,
offset: -2,
formatter: function(value){
return `${value}%`
},
font: {
size: 13
}
},
top: {
color: '#777',
anchor: 'start',
align: 315,
offset: -4,
formatter: function(value, context){
return barChartData.labels[context.dataIndex]
},
font: {
weight: 'bold',
}
}
}
}
The tooltip options will be those from the original code, and a left padding has to be added. Here's the stackblitz fork with this version.