Reputation: 2517
I'm creating a dropdown input using simple div elements. Cause css customisation on native tag is limited.
<div class="dropdown">
<button @click="open=true">{{selected}}</button>
<div class="dropdown-content" v-if="open">
<p @click="setValue()">Hello World!</p>
<p>Hello World!</p>
<p>Hello World!</p>
</div>
</div>
So when the user clicks on the button setValue() method will be fired.
export default {
name: "dropdown",
components: {},
props: [
"value",
],
data() {
return {
selected : null }
},
computed: {},
mounted() {},
methods: {
setValue(value) {
this.open = false;
this.selected = value;
this.$emit("selected", value);
},
},
};
So my question is that how can I bind v-model to this custom component from the outside:
Like this :
<dropdown v-model="dropvalue"></dropdown>
Currently I'm listening to the emit event from the component and manually updating the input value... (something like ...<dropdown @selected="changeValue($event)"></dropdown>
Instead how can I implement something like metioned above ... using v-model???
Upvotes: 1
Views: 1748
Reputation: 1624
Just as an update, I don't think this works in Vue 3 (at least it didn't for me). Here is what I ended up doing:
CustomComponent.vue
<input
type="text"
id="simple-search" @input="setValue"
class="w-full pl-8 p-2 border border-inputborder text-icongrey rounded-lg outline-none"
:placeholder=placeholder
>
The setValue function (I'm using TS but you can just skip the typing for vanilla):
const emit = defineEmits(['update:modelValue'])
const setValue: (event: Event) => void = (event: Event) : void => emit('update:modelValue', (event.target as HTMLInputElement).value)
PageYouWantToUseYourCustomComponent.vue
Somewhere in the page:
<CustomComponent :placeholder="'This is just prop bound'" v-model="searchStr"></CustomComponent>
And in my setup script I have the searchStr as a reactive bit:
const searchStr = ref('')
Upvotes: 0
Reputation: 1
You should emit input
event :
this.$emit("input", value);
Full example :
// ignore the following two lines, they just disable warnings in "Run code snippet"
Vue.config.devtools = false;
Vue.config.productionTip = false;
Vue.component('dropdown', {
name: "dropdown",
props: [
"value","options"
],
data() {
return {
selected: null,
open:false
}
},
methods: {
setValue(value) {
this.open = false;
this.selected = value;
this.$emit("input", value);
},
},
template: `<div class="dropdown">
<button @click="open=true"> {{selected || 'Select a value'}}</button>
<div v-if="open" class="dropdown-content">
<p v-for="option in options" @click="setValue(option)">
{{option}}
</p>
</div>
</div>`
})
let app = new Vue({
el: '#app',
data() {
return {
val: 'a'
}
}
})
.dropdown-content{
box-shadow :0 0 10px #aaa;
padding:10px;
}
.dropdown-content p{
cursor:pointer;
padding:4px;
}
.dropdown-content p:hover{
background:#efefef
}
<link type="text/css" rel="stylesheet" href="//unpkg.com/bootstrap/dist/css/bootstrap.min.css" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.16/vue.js"></script>
<div id="app" class="container">
<dropdown v-model="val" :options="['aaa','bbb','hello']"></dropdown>
<h2>{{val}}</h2>
</div>
Upvotes: 2
Reputation: 14904
You can use v-model
on custom components you need to emit input
this.$emit("input", value)
Vue.component("dropdown", {
template: `<div class="dropdown">
<button @click="open=true">{{value}}</button>
<div class="dropdown-content" v-if="open">
<p v-for="option in options" @click="setValue(option)">option: {{ option }}</p>
</div>
</div>`,
props: ["value"],
data() {
return {
open: false,
options: [1,2,3,4]
}
},
methods: {
setValue(value) {
this.open = false;
this.$emit("input", value);
},
},
})
new Vue({
el: "#app",
data: {
selectedOption: 2
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<p>selected: {{ selectedOption }}</p>
<dropdown v-model="selectedOption" />
</div>
Upvotes: 2