feat(SelectMenu): handle async search (#426)

Co-authored-by: Benjamin Canac <canacb1@gmail.com>
This commit is contained in:
Marc-Olivier Castagnetti
2023-07-18 15:58:16 +02:00
committed by GitHub
parent 46b444a3e0
commit 5f8fe8559f
3 changed files with 76 additions and 10 deletions

View File

@@ -129,6 +129,7 @@ import {
ListboxOptions as HListboxOptions,
ListboxOption as HListboxOption
} from '@headlessui/vue'
import { computedAsync, useDebounceFn } from '@vueuse/core'
import { defu } from 'defu'
import UIcon from '../elements/Icon.vue'
import UAvatar from '../elements/Avatar.vue'
@@ -219,13 +220,17 @@ export default defineComponent({
default: false
},
searchable: {
type: Boolean,
type: [Boolean, Function] as PropType<boolean | ((query: string) => Promise<any[]> | any[])>,
default: false
},
searchablePlaceholder: {
type: String,
default: 'Search...'
},
debounce: {
type: Number,
default: 200
},
creatable: {
type: Boolean,
default: false
@@ -373,15 +378,23 @@ export default defineComponent({
)
})
const filteredOptions = computed(() =>
query.value === ''
? props.options
: (props.options as any[]).filter((option: any) => {
return (props.searchAttributes?.length ? props.searchAttributes : [props.optionAttribute]).some((searchAttribute: any) => {
return typeof option === 'string' ? option.search(new RegExp(query.value, 'i')) !== -1 : (option[searchAttribute] && option[searchAttribute].search(new RegExp(query.value, 'i')) !== -1)
})
})
)
const debouncedSearch = typeof props.searchable === 'function' ? useDebounceFn(props.searchable, props.debounce) : undefined
const filteredOptions = computedAsync(async () => {
if (props.searchable && debouncedSearch) {
return await debouncedSearch(query.value)
}
if (query.value === '') {
return props.options
}
return (props.options as any[]).filter((option: any) => {
return (props.searchAttributes?.length ? props.searchAttributes : [props.optionAttribute]).some((searchAttribute: any) => {
return typeof option === 'string' ? option.search(new RegExp(query.value, 'i')) !== -1 : (option[searchAttribute] && option[searchAttribute].search(new RegExp(query.value, 'i')) !== -1)
})
})
})
const queryOption = computed(() => {
return query.value === '' ? null : { [props.optionAttribute]: query.value }