skip to Main Content

I’m trying to write the code for price input. The task should be simple, but something doesn’t work..
I have a Vue project and I need user to enter the price in input field, where the price should be filling form the last char. Example: start value "00.00"; when user enter "1" then value became "00.01", when user add "4" then value became "00.14", when add 2 then "01.42".

The code is kind of works, but just inputted number staying in input field, even if I add event.target.value = "";

new Vue({
  el: '#app',
  data: {
    price: '00.00'
  },
  methods: {
    handleKeyDown(event) {
      const key = event.key;
      const validKeys = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'];

      if (!validKeys.includes(key)) {
        event.preventDefault();
        return;
      }

      const newPrice = this.price.replace('.', '') + key;
      const parsedPrice = parseFloat(newPrice);

      if (isNaN(parsedPrice) || parsedPrice > 9999) {
        event.preventDefault();
        return;
      }

      const priceWithDecimal = (parsedPrice / 100).toFixed(2);
      this.price = "0" + priceWithDecimal;
      //   event.target.value = "";
      console.log(this.price);
    }
  }
});
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.js"></script>

<div id="app">
  <input type="text" v-model="price" @keydown="handleKeyDown">
</div>

2

Answers


  1. Don’t reinvent the wheel.

    MDN: <input type="number">

    new Vue({
      el: '#app',
      data: {
        price: 0
      },
      watch: {
        price(val) {
          this.price = Math.round(val * 100) / 100;
        }    
      },
      computed: {
        priceFormated() {
          return this.price.toLocaleString('en-US',
          {
              style:"currency", 
              currency:"USD",
              minimumIntegerDigits: 2,
              useGrouping: false
          });
        }
      }
    });
    #app { line-height: 2; }
    [v-cloak] { display: none; }
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.min.js"></script>
    
    <div id="app">
      <input v-model="price" type="number" placeholder="1.0" step="0.01" min="0" max="10" /><br/>
      <button @click="price -= 1">-1</button>
      Price: {{priceFormated}}
      <button @click="price += 1">+1</button>
    </div>
    Login or Signup to reply.
  2. You can watch the price value for changes instead.

    const
      parseValue  = (v) => parseInt(v.trim().replace(/./g, ''), 10),
      formatValue = (v) => (v / 100).toFixed(2).replace(/^(d)(?=.)/, '0$1');
    
    new Vue({
      el: '#app',
      data: {
        price: '00.00'
      },
      watch: {
        price(newValue, oldValue) {
          const parsed = parseValue(newValue);
          this.price = !isNaN(parsed) ? formatValue(parsed) : oldValue;
        }
      }
    });
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.js"></script>
    
    <div id="app">
      <input type="number" v-model="price" step="0.01">
    </div>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search