chore(InputMenu): allow control of search query

This commit is contained in:
Benjamin Canac
2024-01-03 15:13:32 +01:00
parent f735db04d6
commit c2ef6237d8
3 changed files with 66 additions and 6 deletions

View File

@@ -0,0 +1,15 @@
<script setup>
const people = ['Wade Cooper', 'Arlene Mccoy', 'Devon Webb', 'Tom Cook', 'Tanya Fox', 'Hellen Schmidt', 'Caroline Schultz', 'Mason Heaney', 'Claudie Smitham', 'Emil Schaefer']
const selected = ref()
const query = ref('Wade')
</script>
<template>
<UInputMenu
v-model="selected"
v-model:query="query"
:options="people"
placeholder="Select a person"
/>
</template>

View File

@@ -100,6 +100,32 @@ excludedProps:
Learn how to customize icons from the [Input](/forms/input#icon) component.
::
## Searchable
### Attributes
Use the `search-attributes` prop with an array of property names to search on each option object. Nested attributes can be accessed using `dot.notation`. When the property value is an array or object, these are cast to string so these can be searched within.
::component-example
---
component: 'input-menu-example-search-attributes'
componentProps:
class: 'w-full lg:w-48'
---
::
### Control the query
Use a `v-model:query` to control the search query.
::component-example
---
component: 'input-menu-example-search-query'
componentProps:
class: 'w-full lg:w-48'
---
::
## Popper
Use the `popper` prop to customize the popper instance.

View File

@@ -12,7 +12,6 @@
<div :class="uiMenu.trigger">
<HComboboxInput
:id="inputId"
ref="input"
:name="name"
:required="required"
:placeholder="placeholder"
@@ -20,8 +19,8 @@
:class="inputClass"
autocomplete="off"
v-bind="attrs"
:display-value="() => ['string', 'number'].includes(typeof modelValue) ? modelValue : modelValue[optionAttribute]"
@change="query = $event.target.value"
:display-value="() => query ? query : ['string', 'number'].includes(typeof modelValue) ? modelValue : modelValue[optionAttribute]"
@change="onChange"
/>
<span v-if="(isLeading && leadingIconName) || $slots.leading" :class="leadingWrapperIconClass">
@@ -135,6 +134,10 @@ export default defineComponent({
type: [String, Number, Object, Array],
default: ''
},
query: {
type: String,
default: null
},
by: {
type: String,
default: undefined
@@ -256,7 +259,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('input', toRef(props, 'ui'), config, toRef(props, 'class'))
@@ -271,7 +274,16 @@ export default defineComponent({
const size = computed(() => sizeButtonGroup.value || sizeFormGroup.value)
const query = ref('')
const internalQuery = ref('')
const query = computed({
get () {
return props.query ?? internalQuery.value
},
set (value) {
internalQuery.value = value
emit('update:query', value)
}
})
const inputClass = computed(() => {
const variant = ui.value.color?.[color.value as string]?.[props.variant as string] || ui.value.variant[props.variant]
@@ -374,11 +386,16 @@ export default defineComponent({
})
function onUpdate (event: any) {
query.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,
@@ -403,8 +420,10 @@ export default defineComponent({
trailingIconClass,
trailingWrapperIconClass,
filteredOptions,
// eslint-disable-next-line vue/no-dupe-keys
query,
onUpdate
onUpdate,
onChange
}
}
})