I'm trying to figure out how keydown
and change
events work together in Vue.js (Vue 3). The setup is pretty simple. I have a text input in a component, and I want to be able to enter a number in the text input field. From there, I want to be able to use the arrow keys (up and down) to increment or decrement the value in the input. When the input loses focus, it should trigger @change
and then update the model.
This issue I'm having is that when I update the value in the input using @keydown
, it doesn't behave the same way that a keypress for a printable character would. Updating the value on @keydown
doesn't cause the @change
event to be fired when the control loses focus.
I set up an example in the playground if that helps, but here's the code:
App.vue
<script>
import NumberInput from './NumberInput.vue'
export default {
components: {
NumberInput
},
data() {
return {
number: 100
}
}
}
</script>
<template>
<p>
Model should only be updated when focus leaves the text box.
</p>
<p>
This works fine when you type in a number and focus off the text box.
</p>
<p>
However, when you <b>only</b> use the arrow keys to modify a value, the `@change` event doesn't fire.
</p>
<br />
<div style="padding:10px; border:1px solid #aaaaaa">
<NumberInput v-model="number" />
Number: {{ number }}
</div>
</template>
NumberInput.vue
<script>
export default {
props: ['modelValue'],
data() {
return {
number: this.modelValue
}
},
methods: {
incrementOrDecrementNumber: function(e) {
const isUpKey = (e.key === "ArrowUp");
const isDownKey = (e.key === "ArrowDown");
let x = parseInt(this.number, 10);
if (x == NaN)
x = 0;
if (isUpKey || isDownKey) {
if (isUpKey)
x++;
else
x--;
this.number = x;
e.preventDefault();
}
},
numberChanged: function(e) {
this.$emit("update:modelValue", this.number);
}
}
}
</script>
<template>
<div>
Enter a number (press up or down to modify): <input type="text" v-model="number" @change="numberChanged($event);" @keydown="incrementOrDecrementNumber($event);" />
</div>
</template>
Is it possible to update this.number
in the component and also have it fire a @change
event when the input loses focus?
Thanks!