Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Format option to suppress decimals when zero #299

Open
studioghato opened this issue Mar 9, 2021 · 4 comments
Open

Format option to suppress decimals when zero #299

studioghato opened this issue Mar 9, 2021 · 4 comments

Comments

@studioghato
Copy link

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.

@scurker
Copy link
Owner

scurker commented Mar 9, 2021

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.

@studioghato
Copy link
Author

studioghato commented Mar 9, 2021

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

@TimNZ
Copy link

TimNZ commented May 22, 2021

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()
}

@yuklai
Copy link

yuklai commented Jul 15, 2022

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 : ''));
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants