Reputation: 3230
I'm using Charts.js to show a graph on my site. Currently, the label shows as a long string of numbers (i.e 123456). I want it to show as currency with thousands separator: (i.e $123,456)
I'm using the scaleLabel option to put a $ USD symbol before the value:
scaleLabel: "<%= ' $' + Number(value)%>"
and a function to insert the comma separator:
function(label){return label.value.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");}
I just do not know how to use these together to get what I want.
Here is the fiddle: http://jsfiddle.net/vy0yhd6m/79/
(please keep in mind that currently the graph will only work if you remove one of those two pieces of JavaScript cited above)
Thank you for any and all help.
Upvotes: 84
Views: 106100
Reputation: 43
The answers here by Perry Tew, AJ A. et al yield a
Invalid scale configuration for scale: yAxes
error for me. I'm guessing that's because of a change in version 3.
Per the current docs this slight change seems to work:
options: {
scales: {
y: {
ticks: {
callback: function (value, index, values) {
return value.toLocaleString("en-CA", {
style: "currency",
currency: "CAD",
minimumFractionDigits:0,
maximumFractionDigits:0});
}
}
}
}
}
Upvotes: 1
Reputation: 3230
If you are using Charts.js for Angular 2+ (ng2-charts) you can use CurrencyPipe
. Here is how I formatted the label:
Inject the dependency within your page.ts file:
import { CurrencyPipe } from '@angular/common';
Here is how I call it within my chart options:
public chartOptions: any = {
responsive: true,
legend: {
display: false,
labels: {
display: false
}
},
tooltips: {
enabled: true,
mode: 'single',
callbacks: {
label: function(tooltipItem, data) {
let label = data.labels[tooltipItem.index];
let datasetLabel = data.datasets[tooltipItem.datasetIndex].data[tooltipItem.index];
let currencyPipe = new CurrencyPipe('en');
let formattedNumber = currencyPipe.transform(datasetLabel, 'USD', 'symbol');
return label + ': ' + formattedNumber;
}
}
}
};
UPDATE 2022-04-07: The syntax has changed for Chart.js version 3. Here is what the options object looks like if you are using v3:
import { ChartConfiguration, ChartData, ChartType } from 'chart.js';
import { CurrencyPipe } from '@angular/common';
public chart_options: ChartConfiguration['options'] = {
layout: {
padding: 25,
},
responsive: true,
plugins: {
legend: {
display: false,
},
tooltip: {
enabled: true,
callbacks: {
label: function(context) {
let currency_pipe = new CurrencyPipe('en');
return ' ' + context.label + ': ' + currency_pipe.transform(context.parsed, 'USD', 'symbol');
}
}
}
}
};
public chart_type: ChartType = 'doughnut';
public chart_labels: string[] = [];
public chart_data: ChartData<'doughnut'> = {
labels: this.chart_labels,
datasets: [{
data: [],
backgroundColor: [],
}]
};
<div style="display: block;">
<canvas baseChart [data]="chart_data" [options]="chart_options" [type]="chart_type"></canvas>
</div>
Check out the Chart.js v3 Migration Guide for more info
Upvotes: 6
Reputation: 4552
I know my answer is too late but due to op are getting more attention this may relevant now.
Here is the more simple and decent approach.
const formatter = new Intl.NumberFormat("en-US", {
style: "currency",
currency: "USD"
}); // Change locale according to your currency and country
var options = {
scales: {
yAxes: [
{
ticks: {
callback: (label, index, labels) => {
return formatter.format(label);
}
}
}
]
}
}
Upvotes: 4
Reputation: 990
There is a specific javascript function to convert a long number into a number formatted according to system settings: toLocaleString().
You can specify that the label of each tick (or of a specific tick identified by its number index) must be built by your own function, by adding "callback:" keyword inside tick options:
Before:
ticks: {
max: maxAltitude,
min: 0
}
After:
ticks: {
max: maxAltitude,
min: 0, // <--- dont' foget to add this comma if you already have specified ticks options
callback:
function(value, index, valuesArray) {
// value: currently processed tick label
// index of currently processed tick label
// valuesArray: array containing all predefined labels
return value.toLocaleString();
} // Function end
} // Ticks options end
Without the comments and without unused variables:
ticks: {
max: maxAltitude,
min: 0,
callback:
function(value) {
return value.toLocaleString();
}
}
Upvotes: -1
Reputation: 3388
Using chartjs v2.8.0, after looking around the docs, I found it here.
Instead of making my own formatter, I'm using numeraljs to format the number. So this is what I do:
import numeral from 'numeral'
options: {
scales: {
yAxes: [{
ticks: {
callback: function (value, index, values) {
// add comma as thousand separator
return numeral(value).format('0,0')
},
}
}]
},
tooltips: {
callbacks: {
label: function (tooltipItem, data) {
var label = data.datasets[tooltipItem.datasetIndex].label || ''
if (label) {
label += ': '
}
label += numeral(tooltipItem.yLabel).format('0,0')
return label
},
},
},
}
You can use format('$ 0,0')
to add currency symbol along with comma thousand separator.
Upvotes: 5
Reputation: 371
In chartjs v2.0, you can set a global options like this:
Chart.defaults.global.tooltips.callbacks.label = function(tooltipItem, data) {
return tooltipItem.yLabel.toLocaleString("en-US");
};
Chart.scaleService.updateScaleDefaults('linear', {
ticks: {
callback: function (value, index, values) {
return value.toLocaleString();
}
}
});
Upvotes: 8
Reputation: 2632
I'm new to chart.js, but here's what I had to do to make Billy Moon's answer work with the latest version 2.1.6.
var data = {
labels: ["12 AM", "1 AM", "2 AM", "3 AM", "4 AM", "5 AM", "6 AM", "7 AM", "8 AM", "9 AM", "10 AM", "11 AM", "12 PM", "1 PM", "2 PM", "3 PM", "4 PM", "5 PM", "6 PM", "7 PM", "8 PM", "9 PM", "10 PM", "11 PM"],
datasets: [
{
label: "Sales $",
lineTension: 0,
backgroundColor: "rgba(143,199,232,0.2)",
borderColor: "rgba(108,108,108,1)",
borderWidth: 1,
pointBackgroundColor: "#535353",
data: [65, 59, 80, 81, 56, 55, 59, 80, 81, 56, 55, 40, 59, 80, 81, 56, 55, 40, 59, 80, 81, 56, 55, 40]
}
]
};
//var myChart =
new Chart(document.getElementById('sales-summary-today'), {
type: 'line',
data: data,
options: {
animation: false,
legend: {display: false},
maintainAspectRatio: false,
responsive: true,
responsiveAnimationDuration: 0,
scales: {
yAxes: [{
ticks: {
beginAtZero: true,
callback: function(value, index, values) {
if(parseInt(value) >= 1000){
return '$' + value.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
} else {
return '$' + value;
}
}
}
}]
}
}
});
Again, credit goes to Billy Moon's Answer for the label formatting function.
Upvotes: 119
Reputation: 646
I'm mostly summarizing what others have mentioned, but I think the cleanest solution to this exact (and frequently encountered) question is to utilize the toLocaleString
method with USD currency formatting:
return value.toLocaleString("en-US",{style:"currency", currency:"USD"});
This works in all modern browsers. The Mozilla documentation for toLocaleString
lists specific browser compatibility and options for other locales, currencies, and formatting types (e.g. percentages).
Note Chart.js Version 2+ (released in April 2016) requires using the callback
method for advanced tick formatting:
var chartInstance = new Chart(ctx, {
type: 'line',
data: data,
options: {
scales: {
yAxes: [{
ticks: {
callback: function(value, index, values) {
return value.toLocaleString("en-US",{style:"currency", currency:"USD"});
}
}
}]
}
}
});
The syntax if you are using Chart.js Version 1.X would be:
var myLineChart = new Chart(ctx).Line(data, options);
var data = {
...
}
var options = {
scaleLabel: function(label) {
return value.toLocaleString("en-US",{style:"currency", currency:"USD"});
}
Credit to Perry Tew for referencing the syntax change, and to mfink for the idea to use toLocaleString
.
Upvotes: 52
Reputation: 6571
Adding to Perry Tew's answer, if you have negative dollar amounts on your axes (e.g. when displaying a profit/loss chart), you can use this:
ticks: {
callback: function(value, index, values) {
if(parseInt(value) > 999){
return '$' + value.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
} else if (parseInt(value) < -999) {
return '-$' + Math.abs(value).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
} else {
return '$' + value;
}
}
}
The correct format for displaying negative currencies is -$XXX, so we prepend -$
to the value, and then run it through Math.abs(), which converts it to positive.
Upvotes: 10
Reputation: 58521
You should be able to include currency prefix in composition of label inside function...
var options = {
animation: false,
scaleLabel:
function(label){return '$' + label.value.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");}
};
http://jsfiddle.net/vy0yhd6m/80/
Upvotes: 43