0๐
v-combobox
emits change
or input
events only when one of its valid values from the dropdown are selected. The text entered in the combobox is actually search input, used to lookup a valid value; and that entry is bound to v-combobox
โs search-input
prop.
The v-combobox
API lists update:search-input
as an event that is fired when the search input changes, so you could use that to bind the validation handler:
<!-- BEFORE: -->
<v-combobox @input="$v.surname.$touch()">
<!-- AFTER: -->
<v-combobox @update:search-input="$v.surname.$touch()">
0๐
I used to have a component wrapper around v-combobox
, v-autocomplete
and v-select
(yes, single multi-purpose wrapper). And I would recommend using the code below in a wrapper to avoid copy pasting the fix/workaround.
In general workaround required lookup into Vuetify sources. This led to manipulating errorBucket
and valid
in @update:search-input
listener.
Additionally you might want to emit 'input'
. It requires one small tweak to suppress propagation into v-combobox
value, since it breaks autocomplete behavior otherwise. Hence if (this.search) { return; }
Full example: Codepen
Vue.component(
'my-combobox', {
template: `
<v-combobox
ref="combobox"
outlined dense
v-model="selection"
v-bind="{ ...$attrs, items, rules: validationRules }"
v-on="$listeners"
@update:search-input="onSearch"
@focus="touched = true"></v-combobox>
`,
props: {
value: String,
items: Array,
required: Boolean,
rules: Array,
},
data() {
return {
selection: null,
search: null,
touched: false,
};
},
computed: {
validationRules() {
return [
...(this.rules || []),
(v) => !this.required || (v?.length ?? 0) > 0 || 'Value is required',
];
},
},
methods: {
onSearch(v) {
if (!this.touched) return;
this.search = v;
const $self = this.$refs.combobox;
$self.errorBucket = this.validationRules.filter(f => f(v) !== true);
$self.valid = $self.errorBucket.length === 0;
this.$emit('input', v);
},
},
watch: {
selection: {
handler(v) {
this.$emit('input', v);
},
},
value: {
immediate: true,
handler(v) {
if (this.search) { return; }
this.selection = v;
},
},
},
});