Monday, May 20, 2024
 Popular · Latest · Hot · Upcoming
166
rated 0 times [  168] [ 2]  / answers: 1 / hits: 8472  / 2 Years ago, fri, april 8, 2022, 12:00:00

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!


More From » vue.js

 Answers
2

The problem that you're running into is not due to "how keydown and change events work together in Vue.js", and actually has nothing to do with Vue.js per se, but rather is a basic underlying issue with HTML and JavaScript. A change event will be triggered in an input field if the user changes the data of an input field by direct interaction with the field in the web page as this will set the element's "dirty" flag to true.


In your code, while the user's key press actions are triggering the changes, the input value is being changed internally, via JavaScript, and this will not trigger a change event, whether it is being changed through Vue.js or via plain vanilla JavaScript.


To trigger the change event, you can change the input value by a specific means, such as by using setAttribute(value,...) on the input element as per this answer or by directly calling a change event.


In your own code, @blur="numberChanged($event)" could work as noted in my comments:


<input
type="text"
v-model="number"
@change="numberChanged($event)"
@blur="numberChanged($event)"
/>

or you could make the input's value your component's "model" as per Vue.js documentation. I would also make the input type a number, so as to give the input up-down arrow key responsiveness natively:


<script>
export default {
props: ["modelValue"],
emits: ["update:modelValue"],
},
};
</script>

<template>
<div>
<p>
Enter a number (press up or down to modify):
<input
type="number"
:value="modelValue"
@input="$emit('update:modelValue', $event.target.value)"
/>
</p>
</div>
</template>

[#208] Wednesday, March 30, 2022, 2 Years  [reply] [flag answer]
Only authorized users can answer the question. Please sign in first, or register a free account.
gregorio

Total Points: 362
Total Questions: 95
Total Answers: 93

Location: Puerto Rico
Member since Sun, Jun 27, 2021
3 Years ago
gregorio questions
Mon, Sep 6, 21, 00:00, 3 Years ago
Sun, Sep 13, 20, 00:00, 4 Years ago
Mon, Nov 25, 19, 00:00, 5 Years ago
;