CodeSandbox: https://codesandbox.io/s/61my3w7xrw?fontsize=14
I have this renderless component that uses a scoped slot:
name: "BlockElement",
props: {
element: {
type: Object,
required: true
}
},
data() {
return {
inputValue: this.element.value
};
},
render() {
return this.$scopedSlots.default({
inputName: this.inputName,
inputValue: this.inputValue
});
}
Using it like so:
<block-element :element="element" v-slot="{ inputName, inputValue }">
<div>
<input type="text" :name="inputName" v-model="inputValue">
<p>inputValue: {{ inputValue }}</p>
</div>
</block-element>
... so the value is not updated on change. What am I doing wrong?
In the following part of the template
inputValue
is the variable obtained from thev-slot
and not theinputValue
computed property on the<block-element>
component; so if you assign to it (which is whatv-model
does) it won't be calling the setter, it's just setting the value of a local variable in the template code.You could "fix" it like this:
but this is just messy and breaks the abstraction you tried to create.
Another way is to have a
inputValue
setter property on the scope object that will correctly delegate the update to the component:but this isn't ideal either because the scope object isn't typically writable, and this particular implementation detail would need to be documented.
In a situation like this where you want a scoped slot to pass data back to the parent component, you would implement this by passing a callback function to the slot. You can provide a function for setting
inputValue
but then you can't usev-model
:Now there's no confusion about what to do.