I faced an strange issue with Vue3 $emit. I was refactoring my own Vue2 "form-input" -component, which is basically an wrapper for rendering either text-input, (multi)select-option, textarea or any other basic input field.
This component used to bind value against v-model, so it was emitting input via "this.$emit('input', this.value)".
Since Vue 3 changed input to update:modelValue, I made this modification and additionally presented "Emits" -property-list to component. Everything was seemingly working...
But then I recognized that Vue-multiselect 3 (NPM package "vue-multiselect": "^3.0.0-alpha.2") was emitting primitive value, an integer number, which didn't trigger @input on parent-component.
form-input.vue
<input v-if="resolveType === 'text' || resolveType === 'number' || resolveType === 'tel' || resolveType === 'email'"
v-model="localValue"
@input="$emit('update:modelValue', $event.target.value)"
/>
<multiselect v-model="localValue"
class="full-width-tags"
@update:model-value="$emit('update:modelValue', $event)"
/>
// Please note that multiselects $event is an integer, I have checked this multiple times from console.log
... and when I'm listening for @input on parent component it seems "text"-type field triggers event-listener but multiselect doesn't. Only difference on these components is that multiselect is emitting primitive value (integer), while input is sending an event-object.
Could someone explain why event-object and primitive value are handled differently for @input , and how could I fix my multiselects emit so that it's emitting input? Currently I'm emitting both "update:modelValue" AND "input" -events one after another for multiselect, but I'm just wondering if there is easier way?
From your question it seems you have read the Vue 3 Migration Guide - particularly the part about change of v-model
on custom components and changed your form-input
to emit update:modelValue
event instead of input
event
So why are you listening for updates on your form-input
component with @input
instead of @update:modelValue
?
The only reason why the @input
placed on your form-input
component in the parent works, is because of this change
In short - because your component declares that it emits update:modelValue
event (using emits
option), every other event listener placed on it is directly bound to the root element of the component - native <input>
in this case
This is not what you want. Just change <form-input @input="..." />
to <form-input @update:modelValue="..." />