80

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.

NickyTheWrench
  • 3,150
  • 1
  • 23
  • 35

9 Answers9

118

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.

doppelgreener
  • 4,809
  • 10
  • 46
  • 63
Perry Tew
  • 2,632
  • 3
  • 22
  • 25
  • 4
    This is the solution for charts v2. The other solutions listed at http://stackoverflow.com/questions/20371867/chart-js-formatting-y-axis/28700578#28700578 don't seem to work on the latest release – Aaron Lavers Jul 05 '16 at 05:31
  • Awesome. Works like a charm! – Unbreakable Aug 31 '16 at 20:46
  • 17
    thanks! We can also use `toLocaleString` instead of all the regex and conditionals, just simply: `return "$" + parseInt(value).toLocaleString();` – mfink Sep 19 '16 at 13:54
  • 3
    THANK YOU for putting the full options object. When you're an outsider looking for similar answsers you don't know where all these options are nested and we avoid a waste of time. Besides, its absolutely correct and works :p. – Romain Bruckert Aug 23 '17 at 14:19
49

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.

Community
  • 1
  • 1
AJ A.
  • 616
  • 5
  • 7
  • 2
    why would you think this wouldnt work for tooltips ? tried putting this in my tooltip callback, nothing – Jay Rizzi Aug 03 '17 at 14:41
  • 4
    For those who want to remove the decimal points from the currency: `{style:"currency", currency:"USD",minimumFractionDigits:0,maximumFractionDigits:0}` – Preston Badeer Jun 22 '18 at 16:31
  • What if the symbol can change? How can you pass it, and the placement (before/after) the number? – DeltaTango Aug 07 '19 at 16:11
43

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/

Billy Moon
  • 57,113
  • 24
  • 136
  • 237
  • Thank you it worked! I will accept your answer in 7 minutes when the websites allows me to :-) – NickyTheWrench Feb 15 '15 at 05:55
  • 5
    This is only for 1.x of Chart.js, scroll down if you need an answer for 2.x or greater. – Preston Badeer Jun 22 '18 at 16:08
  • this does not work for a "complex" scaleLabel containing multiple values, you need { something1: something1, something2: something2, callback: function(label) etc. etc.} – jumpjack Jul 20 '20 at 08:26
10

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.

Ege Ersoz
  • 6,461
  • 8
  • 34
  • 53
8

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();
        }
    }
});
Justin Moore
  • 827
  • 10
  • 12
Son Dang
  • 341
  • 4
  • 5
5

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

NickyTheWrench
  • 3,150
  • 1
  • 23
  • 35
5

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.

Christhofer Natalius
  • 2,727
  • 2
  • 30
  • 39
4

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);
                    }
                }
            }
        ]
    }
}
Jaison James
  • 4,414
  • 4
  • 42
  • 54
-1

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(); 
                      }
                }
jumpjack
  • 841
  • 1
  • 11
  • 17