chore(InputMenu): handle async search with search prop

This commit is contained in:
Benjamin Canac
2024-01-05 17:30:29 +01:00
parent e4b8fffc32
commit 520624bd64
3 changed files with 55 additions and 1 deletions

View File

@@ -0,0 +1,26 @@
<script setup>
const loading = ref(false)
const selected = ref()
async function search (q) {
loading.value = true
const users = await $fetch('https://jsonplaceholder.typicode.com/users', { params: { q } })
loading.value = false
return users
}
</script>
<template>
<UInputMenu
v-model="selected"
:search="search"
:loading="loading"
placeholder="Search for a user..."
option-attribute="name"
trailing
by="id"
/>
</template>

View File

@@ -126,6 +126,20 @@ componentProps:
---
::
### Async search
Pass a function to the `search` prop to customize the search behavior and filter options according to your needs. The function will receive the query as its first argument and should return an array.
Use the `debounce` prop to adjust the delay of the function.
::component-example
---
component: 'input-menu-example-search-async'
componentProps:
class: 'w-full lg:w-48'
---
::
## Popper
Use the `popper` prop to customize the popper instance.

View File

@@ -99,7 +99,7 @@ import {
ComboboxOption as HComboboxOption,
ComboboxInput as HComboboxInput
} from '@headlessui/vue'
import { computedAsync } from '@vueuse/core'
import { computedAsync, useDebounceFn } from '@vueuse/core'
import { defu } from 'defu'
import { twMerge, twJoin } from 'tailwind-merge'
import UIcon from '../elements/Icon.vue'
@@ -234,10 +234,18 @@ export default defineComponent({
type: String,
default: null
},
search: {
type: Function as PropType<((query: string) => Promise<any[]> | any[])>,
default: undefined
},
searchAttributes: {
type: Array,
default: null
},
debounce: {
type: Number,
default: 200
},
popper: {
type: Object as PropType<PopperOptions>,
default: () => ({})
@@ -358,7 +366,13 @@ export default defineComponent({
)
})
const debouncedSearch = props.search && typeof props.search === 'function' ? useDebounceFn(props.search, props.debounce) : undefined
const filteredOptions = computedAsync(async () => {
if (debouncedSearch) {
return await debouncedSearch(query.value)
}
if (query.value === '') {
return props.options
}