GBP currency conversion of Apex Charts data labels - apexcharts

I'm learning to work with Apexcharts and need to show the labels (Y axis labels an data labels) as currency (GBP) but can't seem to find the right approach. I have looked at the locale code, but really not sure how to integrate this into my chart.
I'm trying to ensure that 1000 become 1,000 etc.
Below is the chart code
<script>
var options = {
series: [
{
name: "Price in £s",
data: [1000, 2000, 2500, 3000, 4800, 6000]
}
],
chart: {
height: 350,
type: 'bar',
id: 'areachart-2',
dropShadow: {
enabled: true,
color: '#000',
top: 18,
left: 7,
blur: 10,
opacity: 0.2
},
toolbar: {
show: false
}
},
colors: ['#f6564d', '#545454'],
dataLabels: {
enabled: false,
textAnchor: 'middle',
formatter: function(val, index) {
return val.toFixed(0);
}
},
stroke: {
curve: 'straight'
},
title: {
text: '',
align: 'left'
},
grid: {
borderColor: '#f1f1f1',
row: {
colors: ['#fff', 'transparent'], // takes an array which will be repeated on columns
opacity: 0.5
},
},
markers: {
size: 100
},
xaxis: {
categories: ['01/05/22','01/06/22','01/07/22','01/08/22','01/09/22','01/10/22'],
title: {
text: 'Month'
}
},
yaxis: {
min:00,
title: {
text: 'Price in GBP',
},
},
legend: {
position: 'top',
horizontalAlign: 'right',
floating: true,
offsetY: 100,
offsetX: 100
}
};
var chart = new ApexCharts(document.querySelector("#chart"), options);
chart.render();
</script>

In yaxis add labels formatter
labels:{
formatter: (value) => {
return `${numberWithCommas(value)} GBP`;
},
},
And use this regex to add commas
function numberWithCommas(x) {
return x.toString().replace(/\B(?<!\.\d*)(?=(\d{3})+(?!\d))/g, ",");
}

Axes labels formatting can be controlled by yaxis.labels.formatter and xaxis.labels.formatter.
yaxis: {
labels: {
formatter: function (value) {
return value + "$";
}
},
},
xaxis: {
labels: {
formatter: function (value) {
return value;
}
}
}

Related

Chartjs scales.xAxis: Property 'title' does not exist on type '_DeepPartialObject

I have upgraded from chartjs v2.8.0 to 4.2.1, and I am trying to set the legend title in a line chart, however I am getting this vscode error...
However if I look at the object, title certainly seems to be there...
Any ideas why I am getting this type error, or alternatively how to set the legend text (dynamically)?
[UPDATE1]
As extra information, here is how I set up my chart (in an Angular component)
/**
* Create the chart and empty data object
*/
private createChart(): void {
if (this.chart !== undefined) {
return;
}
Chart.register(LineController, PointElement, Tooltip, Legend, TimeScale, LinearScale, CategoryScale, LinearScale, LineElement);
this.chartData = {
datasets: [{
fill: false, // shading under the line
data: []
}]
};
const options: ChartOptions = {
plugins: {
legend: {
display: false,
labels: {
padding: 10
}
}
},
elements: {
line: {
borderColor: this.lineColour // line colour
}
},
responsive: true,
maintainAspectRatio: false,
scales: {
x: {
ticks: {
source: 'auto',
maxRotation: 60,
minRotation: 60,
autoSkip: true,
},
grid: {
color: this.gridLinesColor
},
//label: { labelString: '', display: true },
type: 'time',
display: true,
position: 'bottom',
time: {
unit: 'minute',
displayFormats: {
minute: this.runtimeStatusService.getCacheTimePattern()
}
}
},
y:
{
min: 0,
grid: {
color: this.gridLinesColor,
},
}
}
};
this.chart = new Chart(this.chartRef.nativeElement, {
type: 'line',
data: this.chartData,
options
});
}
And this is how I use to be able to set the x Axis legend text (in v2)
this.chart.config.options.scales.xAxes[0].scaleLabel.labelString = legendText;
And it use to show up like this....
So I just want to do the same in v4
I found I could do what I was after by now adding a chart title.
First I add title to the register..
Chart.register(LineController, PointElement, Tooltip, Legend, Title /* <-- add this **/, TimeScale, LinearScale, CategoryScale, LinearScale, LineElement);
Next I add the title to the plugings...
const options: ChartOptions = {
plugins: {
legend: {
display: false, <---- HIDE THIS
position: 'bottom',
labels: {
padding: 10,
}
},
title: {
display: true, <---- SHOW THIS
position: 'bottom',
text: ''
},
},
And now I can set the title at runtime...
this.chart.config.options.plugins.title.text = 'hello';
In my case, this is all I am after...

Multiple bar charts side by side chartjs

I'm trying to create a bar chart that is grouped by the dataset rather than the label in chartjs3 and I'm having no luck. Before I switch over to building in D3, I wanted to check if this achievable within the confines of ChartJS.
Here is a link to a fiddle where I've been playing around with using different dataset structures and options from the Bar chart docs. I suspect that this is outside of the scope of the charting library, or is within the scope, but requires some custom components to be made – I would appreciate if anyone could direct me on what in particular I would need to extend (e.g. is it a case of a custom axes? or more?).
https://jsfiddle.net/f34ucs76/2/
const data = {
labels: [
'2000','2010','2020',
// 'Frogs','Monkeys','Squirrels','Bats'
],
datasets: [
{
label: 'Frogs',
data: [30.2,20.8,36.2],
backgroundColor: 'red',
//stack: 'Frogs',
},
{
label: 'Monkeys',
data: [16.3,13.0,22.3],
backgroundColor: 'blue',
//stack: 'Monkeys',
},
{
label: 'Squirrels',
data: [5.8,3.1,14.9],
backgroundColor: 'cyan',
//stack:'Squirrels',
},
{
label: 'Bats',
data: [0.1,3.6,2.6],
backgroundColor: 'aquamarine',
//stack:'Bats',
},
],
}
const options = {
maintainAspectRatio: false,
responsive: true,
interaction: {
intersect: false,
mode: 'index',
},
plugins: {
title: {
display: false,
},
subtitle: {
display: true,
align: 'start',
text: ['Source: Animals Index, June 2022'],
font: {
size: 12,
style: 'italic',
},
position: 'bottom',
padding: {
top: 20,
},
},
legend: {
display: true,
position: 'bottom',
},
tooltip: {
enabled: true,
},
},
scales: {
x: {
grid: {
display: false,
},
},
y: {
title: {
display: true,
text: 'Horsepower',
},
},
},
}
const mychart = new Chart(
document.getElementById('mychart'),
{
type: 'bar',
data: data,
options: options,
}
);
Your problem can be solved with Chart.js but the labels and the single dataset need to be generated.
Further you need to define your own legend by defining a plugins.legend.labels.generateLabels together with with a plugins.legend.labels.onClick function.
For further information, consult the Legend page from the Chart.js. documentation.
Please take a look at your amended and runnable code below and see how it works.
const baseData = {
labels: ['2000','2010','2020'],
datasets: [
{ label: 'Frogs', data: [30.2, 20.8, 36.2], bgColor: 'red', hidden: false },
{ label: 'Monkeys', data: [16.3, 13.0, 22.3], bgColor: 'blue', hidden: false },
{ label: 'Squirrels', data: [5.8,3.1, 14.9], bgColor: 'cyan', hidden: false },
{ label: 'Bats', data: [0.1, 3.6, 2.6], bgColor: 'aquamarine', hidden: false }
]
};
const iLastDs = baseData.datasets.length - 1;
const data = {
labels: baseData.datasets
.map(() => baseData.labels)
.map((labels, i) => i < iLastDs ? [...labels, null] : labels)
.flatMap(v => v),
datasets: [{
data: baseData.datasets
.map(ds => ds.data)
.map((data, i) => i < iLastDs ? [...data, null] : data)
.flatMap(v => v),
backgroundColor: baseData.datasets
.map(ds => ds.data.map(v => ds.bgColor))
.map((bgColors, i) => i < iLastDs ? [...bgColors, null] : bgColors)
.flatMap(v => v),
categoryPercentage: 1,
barPercentage: 0.9
}]
};
const options = {
maintainAspectRatio: true,
responsive: true,
interaction: {
intersect: true,
mode: 'index',
},
plugins: {
legend: {
position: 'bottom',
labels: {
generateLabels: chart => baseData.datasets.map((ds, i) => ({
datasetIndex: i,
text: ds.label,
fillStyle: ds.bgColor,
strokeStyle: 'lightgray',
hidden: baseData.datasets[i].hidden
}))
},
onClick: (event, legendItem, legend) => {
baseData.datasets[legendItem.datasetIndex].hidden = !baseData.datasets[legendItem.datasetIndex].hidden;
const iFirstValue = legendItem.datasetIndex + legendItem.datasetIndex * baseData.labels.length;
for (let i = iFirstValue; i < iFirstValue + baseData.labels.length; i++) {
legend.chart.toggleDataVisibility(i);
}
legend.chart.update();
}
},
tooltip: {
callbacks: {
title: ctx => {
const dsIndex = Math.floor(ctx[0].dataIndex / baseData.datasets.length);
return baseData.datasets[dsIndex].label + ' / ' + ctx[0].label;
}
}
}
},
scales: {
x: {
grid: {
display: false
}
},
y: {
title: {
display: true,
text: 'Horsepower',
}
}
}
};
new Chart('mychart', {
type: 'bar',
data,
options
});
span {
font-style: italic;
font-size: 12px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.9.1/chart.min.js"></script>
<canvas id="mychart" height="100"></canvas>
<span>Source: Animals Index, June 2022</span>

Tooltip on each data point in Chartjs

Here is my code for putting different tooltip on each data point. I want to put different month on each point, but all the months get printed together. How do I separate them out?
function trendsChart(labels1, datasets1, chartId) {
var ctx =
document.getElementById(chartId).getContext('2d');
var MONTHS = ["January", "February", "March", "April", "May", "June"];
console.log(datasets1)
var data = {
labels: labels1,
datasets: datasets1,
};
// Tooltip
const titleTooltip = (tooltipItems) => {
let sum = 77;
MONTHS.forEach(function(tooltipItem) {
sum = tooltipItem;
})
return sum;
}
var randomScalingFactor = function() {
return (Math.random() > 0.5 ? 1.0 : 1.0) * Math.round(Math.random() * 100);
};
var line1 = [randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor()];
myChart = new Chart(ctx, {
type: 'line',
data: data,
options: {
maintainAspectRatio: false,
responsive: true,
scales: {
x: {
barPercentage: 1.6,
gridLines: {
drawBorder: false,
color: 'rgba(225,78,202,0.1)',
zeroLineColor: "transparent",
},
ticks: {
padding: 0,
fontColor: "#9a9a9a"
},
title: {
display: true,
text: 'Week Of'
}
},
y: {
barPercentage: 1.6,
gridLines: {
drawBorder: false,
color: 'rgba(225,78,202,0.1)',
zeroLineColor: "transparent",
},
ticks: {
padding: 0,
fontColor: "#9a9a9a"
},
stacked: false,
title: {
display: true,
text: 'Count'
}
}
},
plugins: {
tooltip: {
//yAlign: 'bottom',
callbacks: {
title: titleTooltip,
}
}
}
}
});
return myChart;
}
Inside titleTooltip in the pasted code, you replace sum with the last entry from MONTHS. The tooltip from the image however suggests that in the real code, you create an array with 77 and all entries from MONTHS, then you probably return 'Sum: ' + sum, which results in the string you can see in the tooltip.
In order to see all the months on a separate line, you could change your code as follows and return sum as an array:
const titleTooltip = ctx => {
let sum = ['Sum: 77'];
MONTHS.forEach(month => {
sum.push(month);
});
return sum;
}
The resulting tooltip still doesn't make much sense but you'll see all months on a different line. Therefore, you to extend the function titleTooltip in order to obtain the desired result.
Please take a loo at your amended code and see how it works.
function trendsChart(labels1, datasets1, chartId) {
var MONTHS = ["January", "February", "March", "April", "May", "June"];
var data = {
labels: labels1,
datasets: datasets1,
};
// Tooltip
const titleTooltip = ctx => {
let sum = ['Sum: 77'];
MONTHS.forEach(month => {
sum.push(month);
});
return sum;
}
var randomScalingFactor = function() {
return (Math.random() > 0.5 ? 1.0 : 1.0) * Math.round(Math.random() * 100);
};
var line1 = [randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor()];
myChart = new Chart(chartId, {
type: 'line',
data: data,
options: {
maintainAspectRatio: false,
responsive: true,
scales: {
x: {
barPercentage: 1.6,
gridLines: {
drawBorder: false,
color: 'rgba(225,78,202,0.1)',
zeroLineColor: "transparent",
},
ticks: {
padding: 0,
fontColor: "#9a9a9a"
},
title: {
display: true,
text: 'Week Of'
}
},
y: {
barPercentage: 1.6,
gridLines: {
drawBorder: false,
color: 'rgba(225,78,202,0.1)',
zeroLineColor: "transparent",
},
ticks: {
padding: 0,
fontColor: "#9a9a9a"
},
stacked: false,
title: {
display: true,
text: 'Count'
}
}
},
plugins: {
tooltip: {
//yAlign: 'bottom',
callbacks: {
title: titleTooltip,
label: ctx => ctx.label + ': ' + ctx.parsed.y
}
}
}
}
});
return myChart;
}
trendsChart(['created', 'tested', 'reviewed', 'approved'], [{ data: [1, 5, 3, 2]}], 'myChart');
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.8.0/chart.js"></script>
<canvas id="myChart"></canvas>

Add labels to bar chart: chartjs

I am creating bar charts using chartjs 3.5.1, and I am new to chartjs. I want to add value labels to each bar in my bar chart.
I have reviewed some relevant answers, but they are either too old or too complicated to achieve.
Below is the intended outcome, note that the non-hand-written part is what I have achieved.
The code is below:
let chart2 = new Chart('chart2', {
type: 'bar',
data: {
labels: ["a", "b", "c", "d"],
datasets: [{
data: [500, 400, 300, 200],
}]
},
options: {
indexAxis: 'y',
plugins: {
title: {
display: true,
text: "Graph"
},
legend: {
display: false,
}
},
scales: {
y: {
grid: {
display: false
},
},
x: {
grid: {
display: false
}
}
}
},
});
Really appreciate your help!
You can use the chartjs-plugin-datalabels library.
First you'll have to register the plugin, then you can define the desired options inside options.plugins.datalabels.
Please take a look at your amended code and see how it works.
Chart.register(ChartDataLabels);
new Chart('chart2', {
type: 'bar',
data: {
labels: ["a", "b", "c", "d"],
datasets: [{
data: [500, 400, 300, 200],
}]
},
options: {
indexAxis: 'y',
layout: {
padding: {
right: 60
}
},
plugins: {
title: {
display: true,
text: "Graph"
},
legend: {
display: false,
},
datalabels: {
color: 'blue',
anchor: 'end',
align: 'right',
labels: {
title: {
font: {
weight: 'bold'
}
}
}
}
},
scales: {
y: {
grid: {
display: false
},
},
x: {
grid: {
display: false
}
}
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.5.1/chart.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/chartjs-plugin-datalabels/2.0.0/chartjs-plugin-datalabels.min.js"></script>
<canvas id="chart2" height="100"></canvas>

How can I change the color of certain lines in chartjs / vue-chartjs?

I notice that a default bar chart always has a darker zero line. I also notice the horizontal line at -1.0 is also darker. I want those colors to be the same as the grid. How do I do that?
A bare-bones example is shown here:
https://jsfiddle.net/Lnv3cmz0/1/
Vue.component('chart', {
template:`
<canvas></canvas>
`,
props:['type'],
mounted(){
this._chart = new Chart(this.$el, {
type:this.type,
data:[],
})
},
})
//App setup
new Vue({
el:'#vue',
})
Update:
The zeroLine option no longer seems to be available. I am using the latest/greatest Chart (v4.2.0) and no longer have this issue. Below is a sample of what I'm doing
const ctx = document.getElementById('chart') as HTMLCanvasElement;
chart.value = new Chart(ctx, {
type: 'bar',
data: {
datasets: [],
},
options: {
onClick: (evt) => handleOnClick(evt),
interaction: {
mode: 'nearest',
},
plugins: {
legend: {
labels: {
generateLabels(chart) { // other code here }}
}
},
title: {
display: true,
text: 'My Super cool Chart',
},
},
scales: {
x: {
grid: {
color: () => myBackgroundColor,
},
beginAtZero: false,
ticks: {
callback: (value) => doSomethingOnCallaback(value),
// fontColor: myBackgroundColor,
},
type: 'linear',
},
y: {
grid: {
color: () => myBackgroundColor,
},
max: myStart,
min: myEnd,
beginAtZero: false,
ticks: {
callback: (value) => `Tick ${value}`,
stepSize: 15.0,
},
},
},
},
});
The answer is zeroLineColor in the GridLines
https://www.chartjs.org/docs/latest/axes/styling.html#grid-line-configuration