Cheknov
Cheknov

Reputation: 2082

Select currency and show commas and/or decimals in the input

I have a select (currency) and an input (amount)

The input has to show thousands separators (commas ,) for all the currencies and two decimals .00 for all the currencies as well (except for JPY) in real time while the user is typing.

Example input: (JPY) 123456789

Desired result: 123,456,789

Example input: (USD) 123456789.94

Desired result: 123,456,789.94

What I've tried:

Using toLocaleString():

$("#valueInput").on('keyup',function(){
    $("#valueInput").val($("#valueInput").val().toLocaleString());
});

Using split and replace:

$("#valueInput").on('keyup',function(){
    $("#valueInput").val($("#valueInput").val().split(',').join(''));
    $("#valueInput").val(($("#valueInput").val()).replace(/\B(?=(?:\d{3})+(?!\d))/g, ","));
    $("#estimatedValue").val($("#estimatedValueSelect option:selected").text() + " " + $("#valueInput").val());
});

Using toLocaleString() & specifiying a format:

$("#valueInput").on('keyup',function(){
    var value = $("#valueInput").val();
    $("#valueInput").val(value.toLocaleString('en'));
});

None of them worked.

Full code:

$('#valueSelect').on('change', function(){
    if(this.value === 'JPY') {
        $("#valueInput").removeAttr("pattern");
        $("#valueInput").removeAttr("placeholder");
        $("#valueInput").removeAttr("min");
        $("#valueInput").removeAttr("step");
        $("#valueInput").attr("pattern","[0-9]");
        $("#valueInput").attr("title","Numbers only");
        $("#valueInput").attr("placeholder","1000");
    } else {
        $("#valueInput").removeAttr("placeholder");
        $("#valueInput").attr("pattern","^\d+(?:\.\d{1,2})?$");
        $("#valueInput").attr("placeholder","0.00");
        $("#valueInput").attr("min","0");
        $("#valueInput").attr("step","0.01");
    }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<!-- CSS only -->
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" crossorigin="anonymous">

<!-- JavaScript Bundle with Popper -->
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js" integrity="sha384-ka7Sk0Gln4gmtz2MlQnikT1wXgYsOg+OMhuP+IlRH9sENBO0LRn5q+8nbTov4+1p" crossorigin="anonymous"></script>


<div class="col-sm">
    <div class="row">
        <div class="input-group mb-3">
            <div class="input-group-prepend">
                <select  id="valueSelect" class="selectpicker"  aria-label="Currency">
                    <option value="JPY" selected>JPY</option>
                    <option value="USD">USD</option>
                    <option value="EUR">EUR</option> 
                </select>
            </div>
            <input id="valueInput" class="form-control" aria-label="Estimated Value" type="number" placeholder="1000" name="price" pattern="[0-9]" required>
        </div>
    </div>
</div>

I have also implemented the validation part and it works partially, what I can't get to work is displaying a comma , and period . in real time while the user is typing with the restrictions mentioned above.

Upvotes: 1

Views: 1275

Answers (2)

Kien Nguyen
Kien Nguyen

Reputation: 2691

Below is my approach based on your code:

  1. Remove restriction by HTML pattern and change input type to text
  2. Use oninput event handler to remove disallowed characters and convert the number to desired format

let maximumFractionDigits = 0
const valueInput = $("#valueInput");
const formatNumber = (value) => {
  return parseFloat(value.replace(/,/g,'')).toLocaleString('en-US', { maximumFractionDigits });
}

$('#valueSelect').on('change', function(){
  if(this.value === 'JPY') {
    maximumFractionDigits = 0
    valueInput.removeAttr("pattern");
    valueInput.removeAttr("placeholder");
    valueInput.removeAttr("min");
    valueInput.removeAttr("step");
    valueInput.attr("title","Numbers only");
    valueInput.attr("placeholder","1000");
  } else {
    maximumFractionDigits = 2
    valueInput.removeAttr("placeholder");
    valueInput.attr("pattern","^\d+(?:\.\d{1,2})?$");
    valueInput.attr("placeholder","0.00");
    valueInput.attr("min","0");
    valueInput.attr("step","0.01");
  }
  valueInput.val(formatNumber(valueInput.val()));
});

valueInput.on('input', function() {
  if (!this.value || (maximumFractionDigits && this.value.endsWith('.'))) {
    return
  }
  $(this).val(formatNumber(this.value));
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<!-- CSS only -->
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" crossorigin="anonymous">

<!-- JavaScript Bundle with Popper -->
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js" integrity="sha384-ka7Sk0Gln4gmtz2MlQnikT1wXgYsOg+OMhuP+IlRH9sENBO0LRn5q+8nbTov4+1p" crossorigin="anonymous"></script>


<div class="col-sm">
    <div class="row">
        <div class="input-group mb-3">
            <div class="input-group-prepend">
                <select  id="valueSelect" class="selectpicker"  aria-label="Currency">
                    <option value="JPY" selected>JPY</option>
                    <option value="USD">USD</option>
                    <option value="EUR">EUR</option> 
                </select>
            </div>
            <input id="valueInput" class="form-control" aria-label="Estimated Value" type="text" placeholder="1000" name="price" required>
        </div>
    </div>
</div>

Upvotes: 1

mamady
mamady

Reputation: 178

You're looking for Intl.NumberFormat. From the documentation:

console.log(new Intl.NumberFormat('en-US',).format(123456789.94));

You can use any language format you want.

Upvotes: 0

Related Questions