2

I have the following Vue code:

// HTML
<div id="app">
  Value: <pre>{{ value }}</pre>
  <input type="text" :value="value" @input="setValue">
</div>

// JS
new Vue({
  el: "#app",
  data: {
    value: '',
  },
  methods: {
    setValue(event){
      /* Remove non-numeric values */
        this.value = event.target.value.replace(/[^\d]/g, '');
    }
  }
});

I have it set up on JSFiddle here: http://jsfiddle.net/eywraw8t/353729/.

Why does the input allow me to enter non-numeric values?

If you run the code above, and enter non-numeric gibberish into the input element (e.g. asdasfa), you'll see that the input element will contain your entered text (asdasfa), but the element above the input will be empty!

I would like to restrict users to only being allowed to enter numbers into the input. I would like to do this using only Vue, no 3rd party libraries or type="number".

0

2 Answers 2

3

because the value of this.value doesn't change (always ='') so it will not trigger re-render.

The solution:

you can use this.$forceUpdate() to force re-render.

or use bind key with different value.

new Vue({
  el: "#app",
  data: {
    value: '',
    errorDescription: ''
  },
  methods: {
  	setValue(event){
      /* Remove non-numeric values */
    	this.value = event.target.value.replace(/[^\d]/g, '')
      this.errorDescription = 'Only Number allow'
      this.$forceUpdate()
    }
  }
})
.error {
  background-color:red;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.16/vue.js"></script>
<div id="app">
  Value: <pre>{{ value }}</pre><span class="error">{{errorDescription}}</span>
  <input type="text" :value="value" @input="setValue">
</div>

Sign up to request clarification or add additional context in comments.

4 Comments

Saying "this.value doesn't change" doesn't seem correct. It's definitely changing and doing so in a way that Vue is able to handle reactively. The issue is that :value only binds once
probably I used wrong words to decribe it. but you can check the source code for Vue observer, if the value doesn't change, it will not trigger reactivity.
I'll look into the source code later, thanks for the link. This is what I assumed though. If I enter a bunch of non-numeric characters, the value remains the same, '', as soon as I enter a single numeric character, the rest of the input is replaced with that numeric character.
I now understand what you're saying about the value not changing and therefore not triggering a reactive change in the UI. That's very well spotted. +1
1

The issue is Vue doesn't see a change to your value data property because when you filter out non-numbers, you are essentially assigning the same string value back to it. Since strings are immutable and identical when their contents are the same, this doesn't trigger Vue's reactivity.

An easy solution is to manually set the <input> value to the new, number-only value.

this.value = event.target.value = event.target.value.replace(/\D/g, '')

http://jsfiddle.net/9o2tu3b0/

5 Comments

How can I restrict the input with v-model though?
@chipit24 your original code should work, just switch :value to` v-model. The directive updates the <input>` value for you
Thanks. I assumed v-model would overshadow @input; kind of odd using both of those, no? Since v-model is essentially syntactic sugar for v-bind and @input.
Clearly, they do, and I appreciate you making this evident to me. My concern was that I haven't seen them used together before, so it could lead to a little confusion for other developers looking at such code, as it has for me.
@Sphinx you're right. I got confused with what's happening. The reason v-model gets around this issue is because it first sets the bound property to whatever is typed in, then it's changed again via the @input handler. I'll remove the part about v-model as it's not optimal

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.