1👍
What you are seeing is actually the parent’s default <input>
. So you understand what I mean, add some text to both, like:
<slot name="test" :name="name">
Default: <input type="text" v-model="name">
</slot>
<div slot="test" slot-scope="props">
Actual: <input type="text" v-model="props.name">
</div>
You’ll see that what appears is the default
.
Now, that happens because, it seems like a bug, when the slot prop has the same name as the parent’s, the slot does not work.
Workaround: rename the slot prop.
In the example below, I renamed it from name
to namex
. Notice the v-model
in the default remains the same name
because anything in the template refers to the props of that template (in other words, slot props, e.g. namex
, will never be available in the parent default slot).
<slot name="test" :namex="name">
Default: <input type="text" v-model="name">
</slot>
<div slot="test" slot-scope="props">
Actual: <input type="text" v-model="props.namex">
</div>
1👍
to use v-model
in scoped slots, the value of v-model
must be one level deeper:
Vue.component('render-props', {
data: () => ({message: 'hello', obj: {msg: 'obj_msg'}}),
template: `<div>
<slot name="a" :message="message">
default: {{message}}
<input v-model="message"/>
</slot>
<slot name="b" :obj="obj">
default: {{obj.msg}}
<input v-model="obj.msg"/>
</slot>
</div>`
});
new Vue({
el: "#root",
template: `<div>
<render-props>
<template v-slot:a="props">
actual: {{props.message}}
<input v-model="props.message"/>
</template>
<template v-slot:b="props">
actual: {{props.obj.msg}}
<input v-model="props.obj.msg"/>
</template>
</render-props>
<cus_2 />
</div>`
});
Another easier case:
var Sub = Vue.extend({
props: ['a', 'b'],
template: `<div>
<div>a : <input v-model="a" /></div>
<div>b.txt : <input v-model="b.txt" /></div>
</div>`
});
var Main = Vue.extend({
components: { Sub },
data() {
return {
a: 'aaa',
b: { txt: 'bbb' },
c: 'ccc',
};
},
template: `<div>
<Sub :a="a" :b="b" />
<div>c : <input v-model="c" /></div>
<ul>
<li>a: {{a}}</li>
<li>b.txt: {{b.txt}}</li>
<li>c: {{c}}</li>
</ul>
</div>`
});
new Main().$mount("#app");
a
won’t change, b.txt and c
is ok.
- [Vuejs]-Vue – directive bind doesn't work on element refresh
- [Vuejs]-Error: Error: the "filename" option is required to use includes and extends with "relative" paths
0👍
you are not supposed to modify the data you pass to a slot, pretty
much like a prop. You should pass a method instead to change tha
value. You can always pass an object and modify a property (like a
prop) but it’s also not recommended
-from https://github.com/vuejs/vue/issues/9726
So I imagine something like
<template>
<slot v-bind:value="value"></slot>
</template>
<script>
export default {
name: 'FooBar',
data() {
value: '',
},
methods: {
updateValue(e) {
this.value = e.target.value;
}
},
};
</script>
Then when using the component <FooBar>
instead of using v-model
, you can use the passed scoped slot props, the method (updateValue
), and actual prop that will be updated, value
.
<FooBar v-slot="slotProps">
<input type="text" :value="slotProps.value" @input="slotProps.updateValue" />
</Foobar>