Convert input value to currency format when user type

16,587

Solution 1

There are a couple of problems with your code:

  1. You're using comma when binding multiple event handlers to the input box.
  2. You're not converting the received value to a number before applying toLocaleString on it.
  3. You're not setting the value of the textbox again after conversion.

Correcting these, here is a working demo. For the sake of simplicity, I've removed the other event handlers, except blur, as keyup was causing problems.

$('input.CurrencyInput').on('blur', function() {
  const value = this.value.replace(/,/g, '');
  this.value = parseFloat(value).toLocaleString('en-US', {
    style: 'decimal',
    maximumFractionDigits: 2,
    minimumFractionDigits: 2
  });
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input class="CurrencyInput">

Solution 2

Parse value to specific Locale Currency

The below function will try to parse any gibberish input value to a specific currency.
Useful if you don't want to force users to input values in a specific locale format.

Caveat:

Since the input can literally be gibberish like 1,2.3.45,5 and still give a valid output (like i.e USD: "12,345.50"), there's a small but user friendly caveat:

// Example: conversion to HRK (Format: n.nnn,nn)
INPUT: "0.575"   OUTPUT: "0,58"      // smart guessed: decimals
INPUT: "1.575"   OUTPUT: "1.575,00"  // smart guessed: separator

Example:

/**
 * Parse value to currency
 * @param {number|string} input
 * @param {string} locale - Desired locale i.e: "en-US" "hr-HR"
 * @param {string} currency - Currency to use "USD" "EUR" "HRK"  
 * @return {object} 
 */
const parse = (input, locale = "en-US", currency = "USD") => {
  let fmt = String(input)
    .replace(/(?<=\d)[.,](?!\d+$)/g, "")
    .replace(",", ".");
  const pts = fmt.split(".");
  if (pts.length > 1) {
    if (+pts[0] === 0) fmt = pts.join(".");
    else if (pts[1].length === 3) fmt = pts.join("");
  }
  const number = Number(fmt);
  const isValid = isFinite(number);
  const string = number.toFixed(2);
  const intlNFOpts = new Intl.NumberFormat(locale, {
    style: "currency",
    currency: currency,
  }).resolvedOptions();
  const output = number.toLocaleString(locale, {
    ...intlNFOpts,
    style: "decimal",
  });
  return {
    input,
    isValid,
    string,
    number,
    currency,
    output,
  };
};

Example test:

/**
 * Parse value to currency
 * @param {number|string} input
 * @param {string} locale - Desired locale i.e: "en-US" "hr-HR"
 * @param {string} currency - Currency to use "USD" "EUR" "HRK"  
 * @return {object} 
 */
const parse = (input, locale = "en-US", currency = "USD") => {
  let fmt = String(input)
    .replace(/(?<=\d)[.,](?!\d+$)/g, "")
    .replace(",", ".");
  const pts = fmt.split(".");
  if (pts.length > 1) {
    if (+pts[0] === 0) fmt = pts.join(".");
    else if (pts[1].length === 3) fmt = pts.join("");
  }
  const number = Number(fmt);
  const isValid = isFinite(number);
  const string = number.toFixed(2);
  const intlNFOpts = new Intl.NumberFormat(locale, {
    style: "currency",
    currency: currency,
  }).resolvedOptions();
  const output = number.toLocaleString(locale, {
    ...intlNFOpts,
    style: "decimal",
  });
  return {
    input,
    isValid,
    string,
    number,
    currency,
    output,
  };
};

// TEST:
[
  // Valid values
  "2e5",
  "1,2.3,10,6",
  "0.575",
  "1.575",
  "2.30",
  "1.000.00",
  "1.000",
  1000,
  1,
  ".4",
  "4.",
  "0.25",
  "0.076",
  "1.076",
  0.3478,
  "0.05",
  "123,123",
  "3.000,333.444,009",
  "123,123.80",
  "23.123,80",
  "23.123,8",
  "23.4",
  
  // Invalid values
  null,
  NaN,
  Infinity,
  "a",
].forEach((val) => {
  const p = parse(val, "hr-HR", "HRK");
  console.log(`INP: ${p.input}\t OUT: ${p.output}`);
});
.as-console-wrapper {min-height: 100vh;}

Documentaion:

Share:
16,587
AlonsoCT
Author by

AlonsoCT

I need to learn more and more everyday

Updated on June 05, 2022

Comments

  • AlonsoCT
    AlonsoCT about 2 years

    I have failed to convert the input value to currency format. I want to automaticly add thousands and decimal separators when the user types the number (5,000.00; 125,000.00).

    Here's my code :

    $('input.CurrencyInput').on('blur, focus, keyup',
        function() {
            $(this).val().toLocaleString('en-US', {
                style: 'decimal',
                maximumFractionDigits: 2,
                minimumFractionDigits: 2
            });
        });