Closed sawden closed 3 months ago
Strictly speaking this is not really a bug as the custom element does what it's supposed to do: it emits the component event as a custom event. The problem is that v-model listens for input
but the custom element emits an update:modelValue
event.
However we should discuss how we can better support this common usecase.
On second thought, I'm inclined to rate this as a bug. There's a few different aspects to this, the thing to discuss is wethe we want to support v-model on a custom element at all. We currently support it on distinct native input elements only (and components, but we are dealing with a custom DOM element here).
If we decided to do this, we would have to make the v-model listener deal with custom events, where the emitted value is found in a detail
property. This would complicate things quite a bit.
But regardless of that discussion, the thing that makes it a bug right now, though, is that there's no way to actually listen to the update:modelValue
event though - because we explicitly skip these special events on DOM elements (because they get special treatment on native inputs).
So even if the consumer doesn't use v-model and tries the following, they will fail:
<custom-element :model-value="value" @update:model-value="value = $event.detail"
...because the event listener is never being applied to the custom element. Which is desirable for normal DOM elements, of course, but poses an issue here.
I'll think a bit about it and write more thoughts later
The styles of child vue component are not applied if the parent component is a custom element. #4309 Because of this, I have to define my custom input as a custom element, otherwise I cannot use any styles.
I thank you for your help and hope that a solution/workaround will be found soon. 🙂
✌ue is awesome!
I didn't want to create another issue for it, as this seems related:
v-model does not work on <component :is="...">
components either.
Reproduction: https://codesandbox.io/s/customelement-v-model-bug-forked-w4p21s?file=/src/App.vue
For <component is="input">
one could use @input="value = $event.target.value"
But I would have rather used v-model
which worked in Vue 2
Bumped into this as my use case for this was single component for both textarea and input.
@LinusBorg Did you think about it? It's November 2023 and this is still an issue. It's also a regression from Vue 2.x (https://www.digitalocean.com/community/tutorials/how-to-add-v-model-support-to-custom-vue-js-components) and is blocking me personally from achieving my goal of creating custom elements that do support v-model (like a custom
I have a PR up that addresses this issue (at least partially) for custom elements.
It allows you to specify a v-model
type for different custom elements (like checkbox
, radio
, etc.). Library authors will need to mirror native input props (e.g. value
, checked
) and input
/change
events (while also mirroring changes to value
/checked
on the host element so that updated values are in event.target
), but it'll be possible to make v-model
form bindings work across different types of custom elements.
First of all, a general opinion: Vue custom elements are first and foremost custom elements, so they should strive to behave like native DOM elements where applicable. It is discouraged to author Vue custom elements that only work in Vue applications.
With that in mind, a Vue custom input element should behave like a native <input>
element as much as possible - i.e. expose a value
property, and emit input
events. This makes it possible to both work with v-model
when used inside a Vue app, and also be usable when it's used in a non-Vue environment.
When v-model
is used on a custom element, Vue should treat it the same way whether the custom element is a Vue one or not. So it will listen for the update
event and attempts to read the .value
property.
Therefore, to make a Vue custom element work with v-model
, it should:
value
prop.value
property on the host element and (2) emit an input
event.Before 3.5, retrieving the host element can be a bit difficult. That's why 3.5 will ship with a new useHost()
helper and expose this.$host
for Options API.
Here's a working example using the minor
branch (to be published as 3.5).
Thanks for adding useHost()
that will make updating the host element much easier. With regard to using radio and checkbox custom elements with v-model
, is the recommendation to use type="checkbox"
or type="radio"
to have Vue apply the correct type of v-model
?
I'd be happy to raise a PR to mention this in the Vue docs, if so!
There is a bit more detail in this feature discussion around why I think this would be a helpful thing to document or have an official solution for, https://github.com/vuejs/rfcs/discussions/617:
Setting app.config.compilerOptions.isCustomElement
works well for text input components where I can emit an input
event and use a value
prop, but I am unable to support checkboxes and radio buttons since V_MODEL_DYNAMIC
is looking for event.target.value
instead of event.target.checked
.
The workaround here is to set a type
on the host element like this:
<template>
<custom-checkbox type="checkbox" v-model="value">Label</custom-checkbox>
</template>
<script>
import "@custom-element-package/checkbox.js"
export default {
data() {
return {
value: true
};
},
};
</script>
Version
3.2.4
Reproduction link
CodeSandbox Link
Steps to reproduce
Create a custom input as a CustomElement and use it in a Vue component.
What is expected?
The value specified in the v-model changes
What is actually happening?
v-model is ignored.