Reputation: 1485
I got stuck, guys. Maybe there is simple solution to my problem. Please, help me. Here is the issue.
I have 5 possible options to choose from. Let's say [a, b, c, d, e]
My layout is two buttons and select dropdown menu. In other words, I give two possibilities to user:
Either click on one of two buttons or select from list.
So template is kinda
<button> A <button>
<button> B <button>
<select v-model="selected">
<option :value="i" v-for="i in list">i</option>
</select>
In my script I have
data () {
return {
list: ['c', 'd', 'e']
}
}
How can I combine these three elements into one. Can I somehow use v-model? Cause of now, I can get selected option from list. What should I do then. If I add @click event to buttons, what should they handle?
I thought to make computed value, like checking if selected
is not undefined or equal to ''
, then the option is selected
. But in order to bind buttons clicked events, I should create methods to handle their state, like
data () {
return {
list: ['c', 'd', 'e'],
a: false,
b: false
}
},
methods: {
handleA () {
this.a = true
this.b = false
},
handleB () {
this.b = true
this.a = false
}
}
And then every click will change false
to true
, and besides there also needs to be a logic to keep only one true
state: either for a
(button A), b
(button B) or selected
. It feels too wrong to be true. In my opinion, I'm making things harder. There has to be an easy way.
Upvotes: 1
Views: 7575
Reputation: 43899
The basic problem is that if you v-model
in a select and the variable bound to the v-model
gets a value that is not in your options, the variable gets reset to null.
You have to come up with some special-case handling to get around that. One way is to set the select list to v-model
a settable computed that interprets non-listed values as null and writes non-null values to the selected
data item.
new Vue({
el: '#app',
data: {
selected: null,
list: ['c', 'd', 'e']
},
computed: {
proxySelected: {
get() {
return this.list.includes(this.selected) ? this.selected : null;
},
set(newValue) {
if (newValue) {
this.selected = newValue;
}
}
}
}
});
<script src="//cdnjs.cloudflare.com/ajax/libs/vue/2.3.3/vue.min.js"></script>
<div id="app">
<button @click="selected = 'a'"> A </button>
<button @click="selected = 'b'"> B </button>
<select v-model="proxySelected">
<option :value="i" v-for="i in list">{{i}}</option>
</select>
Selected value: {{selected}}
</div>
Upvotes: 1
Reputation: 82469
I'd recommend a component. Build the component to support v-model
.
Vue.component("picker",{
props:["value"],
data(){
return {
list:["c","d","e"],
currentValue: this.value,
selectedValue: ""
}
},
template:`
<div>
<button @click="currentValue = 'a'">A</button>
<button @click="currentValue = 'b'">B</button>
<select @change="currentValue = $event.target.value" v-model="selectedValue">
<option value="">Select a value</option>
<option v-for="item in list" :value="item" :key="item">{{item}}</option>
</select>
</div>
`,
watch:{
currentValue(newValue){
if (!this.list.includes(newValue))
this.selectedValue = ""
this.$emit('input', newValue)
}
}
})
new Vue({
el:"#app",
data:{
pickedValue: null
}
})
Upvotes: 1