scurker / currency.js

A javascript library for handling currencies

Home Page:https://currency.js.org

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Format option to suppress decimals when zero

studioghato opened this issue · comments

Would it be possible to add an option to suppress decimals when they are zero?

I am usingprecision: 2, but I would like not to get decimals when the returned value contains ".00".
This options should always consider the value of precision to only suppress them when all decimals where zero.

commented

You could use a custom formatter:

const formatter = (currency, settings) => {
  if (!currency.cents()) {
    return currency.value;
  }
  return currency.value.toFixed(settings.precision);
};
const c = value => currency(value, { formatter });

This is a poor man's version of the formatter as it doesn't take into account decimal or group separators, but you use a variation of the default formatter for your needs.

Thank you very much for your quick response, @scurker.

I see. In that case, then I should also handle all the formatting options that I pass in along with the callback "format", don't I?

Because I've already test it, and it doesn't work in a chainable way. With this I mean that I would like to pass in some options, and just tweak the string returned by currency(value, { ...some options... }).format().
This way, I could leverage the inner logic of this (really useful!) library and modify the string by checking just a few options (format and negativeFormat to check if the numbers are at the end; and decimal to be able to find the last digits).

Is it possible to achieve that?

EDIT: maybe that could seem a "dumb question", since I already know the passed in options and can check them once I get the value from currency to tweak the value. But in the case of not having provided custom options, it would really make sense to be able to handle everything from within the "format" callback, since I would then have access to the default options values. Otherwise, if I handled it from the outside, I would have to check the current default values from the documentation, which could change in the future. And it wouldn't be future proof.

By the way, I've found out that, when using comma as decimal and calling currency in the documented way , I don't get the expected result (the value of separator can be anything, since it returns the same value no matter what):

const options = {
   separator: '.',
   decimal: ',',
   precision: 2,
   symbol: '' // Notice here that I am forcing the library not to display the currency symbol in order to also use it with non-currency values.
}

// Documented way to pass in options, but undesired result when passed in as a string
currency(25.01, options).format() //-> 25,00 -- OK
currency('25.01', options).format() //-> 2.501,00 -- NOT OK
currency('25,01', options).format() //-> 25,01 -- OK

// Undocumented way to pass in options (is it trully invalid?), but desired result
currency(25.01).format(options) //-> 25,01 -- OK
currency('25.01').format(options) //-> 25,01 -- OK

Is it as simple as this?
I cloned the default format func and simply null cents if it parses as 0.
You could control this via a param/flag.

function currencyFormater(currency, settings) {
  let { pattern, negativePattern, symbol, separator, decimal, groups } = settings
    , split = ('' + currency).replace(/^-/, '').split('.')
    , dollars = split[0]
    , cents = split[1];
   if (parseInt(cents) == 0)
	cents = null
  return (currency.value >= 0 ? pattern : negativePattern)
    .replace('!', symbol)
    .replace('#', dollars.replace(groups, '$1' + separator) + (cents ? decimal + cents : ''));
}
const currencyFormat = (val,options) => {
	return currency(val,{format: currencyFormater}).format()
}

Would be great if this is actually added as an option I feel.

I modified @TimNZ's answer to allow for cases for the following:
123.0 => '123'
123.4 => '123.4'
123.40 => '123.4'
123.45 => '123.45'

export function exactDecimalFormatter(currency, settings) {
  let { pattern, negativePattern, symbol, separator, decimal, groups } = settings
    , split = ('' + currency).replace(/^-/, '').split('.')
    , dollars = split[0]
    , cents = split[1];

  let centsInNumber = parseInt(cents);
  while (centsInNumber % 10 === 0 && centsInNumber !== 0) {
    centsInNumber /= 10;
  }

  return (currency.value >= 0 ? pattern : negativePattern)
    .replace('!', symbol)
    .replace('#', dollars.replace(groups, '$1' + separator) + (centsInNumber > 0 ? decimal + centsInNumber : ''));
}