Reputation: 18745
I'm trying to create a customCombobox
component that works like a normal v-combobox
with one addition - after user presses tab
key, it will select the first option automatically (if there are any).
What I've done so far looks good but v-model
on this field doesn't work (it's always null
).
<template>
<v-combobox ref="combobox" :rules="rules"
@keydown.tab.prevent="selectFirst"
:value="innerValue" :label="label"
:items="items"
>
</v-combobox>
</template>
<script>
module.exports = {
props: ['value', 'label', 'items', 'rules'],
data() {
return {
innerValue:null,
}
},
watch:{
value(_new){
this.innerValue = _new
this.$emit('input',[_new])
this.$emit('change')
}
},
methods: {
selectFirst() {
var combobox = this.$refs.combobox
var filteredItems = combobox.filteredItems
if (filteredItems.length){
this.innerValue = filteredItems[0]
}
}
},
computed: {
}
}
</script>
Do you know why?
Upvotes: 3
Views: 2921
Reputation: 63129
You can use a computed setter in the custom component to handle the v-model
from the parent and pass it down to its own child v-combobox
:
Custom component:
<v-combobox v-model="selected" v-bind="$attrs"></v-combobox>
computed: {
selected: {
get() {
return this.value;
},
set(val) {
this.$emit('input', val);
}
}
}
Using v-bind="$attrs"
also passes down all of the props from the parent. Here's a demo:
Vue.component('comp', {
props: ['value'],
template: `
<v-combobox v-model="selected" v-bind="$attrs"></v-combobox>
`,
computed: {
selected: {
get() {
return this.value;
},
set(val) {
this.$emit('input', val);
}
}
}
})
new Vue({
el: '#app',
vuetify: new Vuetify(),
data() {
return {
selected: 'Vue',
label: 'This is my label',
rules: ['These are my rules'],
items: ['Programming', 'Design', 'Vue', 'Vuetify']
}
}
})
#app {
padding: 48px;
}
<div id="app">
<v-app id="inspire">
Selected in parent: {{ selected }}
<comp
v-model="selected"
:label="label"
:items="items"></comp>
</v-app>
</div>
<link href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/@mdi/[email protected]/css/materialdesignicons.min.css" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/vuetify.min.css" rel="stylesheet">
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vuetify.js"></script>
Upvotes: 5