diff --git a/docs/components/content/examples/SelectMenuExampleSearchQuery.vue b/docs/components/content/examples/SelectMenuExampleSearchQuery.vue
new file mode 100644
index 0000000000..db05eafb21
--- /dev/null
+++ b/docs/components/content/examples/SelectMenuExampleSearchQuery.vue
@@ -0,0 +1,16 @@
+
+
+
+
+
diff --git a/docs/content/3.forms/4.select-menu.md b/docs/content/3.forms/4.select-menu.md
index c31451b918..62029af8fe 100644
--- a/docs/content/3.forms/4.select-menu.md
+++ b/docs/content/3.forms/4.select-menu.md
@@ -146,6 +146,18 @@ componentProps:
---
::
+### Control the query :u-badge{label="New" class="align-middle ml-2 !rounded-full" variant="subtle"}
+
+Use a `v-model:query` to control the search query.
+
+::component-example
+---
+component: 'select-menu-example-search-query'
+componentProps:
+ class: 'w-full lg:w-48'
+---
+::
+
## Creatable
Use the `creatable` prop to enable the creation of new options when the search doesn't return any results (only works with `searchable`).
diff --git a/src/runtime/components/forms/SelectMenu.vue b/src/runtime/components/forms/SelectMenu.vue
index e87abcab96..f68a0465c5 100644
--- a/src/runtime/components/forms/SelectMenu.vue
+++ b/src/runtime/components/forms/SelectMenu.vue
@@ -58,14 +58,13 @@
import { ref, computed, toRef, watch, defineComponent } from 'vue'
-import type { PropType, ComponentPublicInstance } from 'vue'
+import type { PropType } from 'vue'
import {
Combobox as HCombobox,
ComboboxButton as HComboboxButton,
@@ -177,6 +176,10 @@ export default defineComponent({
type: [String, Number, Object, Array],
default: ''
},
+ query: {
+ type: String,
+ default: null
+ },
by: {
type: String,
default: undefined
@@ -326,7 +329,7 @@ export default defineComponent({
default: () => ({})
}
},
- emits: ['update:modelValue', 'open', 'close', 'change'],
+ emits: ['update:modelValue', 'update:query', 'open', 'close', 'change'],
setup (props, { emit, slots }) {
const { ui, attrs } = useUI('select', toRef(props, 'ui'), config, toRef(props, 'class'))
@@ -341,8 +344,16 @@ export default defineComponent({
const size = computed(() => sizeButtonGroup.value || sizeFormGroup.value)
- const query = ref('')
- const searchInput = ref>()
+ const internalQuery = ref('')
+ const query = computed({
+ get () {
+ return props.query ?? internalQuery.value
+ },
+ set (value) {
+ internalQuery.value = value
+ emit('update:query', value)
+ }
+ })
const selectClass = computed(() => {
const variant = ui.value.color?.[color.value as string]?.[props.variant as string] || ui.value.variant[props.variant]
@@ -476,17 +487,15 @@ export default defineComponent({
})
function onUpdate (event: any) {
- if (query.value && searchInput.value?.$el) {
- query.value = ''
- // explicitly set input text because `ComboboxInput` `displayValue` is not reactive
- searchInput.value.$el.value = ''
- }
-
emit('update:modelValue', event)
emit('change', event)
emitFormChange()
}
+ function onChange (event: any) {
+ query.value = event.target.value
+ }
+
return {
// eslint-disable-next-line vue/no-dupe-keys
ui,
@@ -512,8 +521,10 @@ export default defineComponent({
trailingWrapperIconClass,
filteredOptions,
createOption,
+ // eslint-disable-next-line vue/no-dupe-keys
query,
- onUpdate
+ onUpdate,
+ onChange
}
}
})