mirror of
https://github.com/element-plus/element-plus.git
synced 2024-11-27 02:01:15 +08:00
feat(components): [autocomplete] fetchSuggestions supports Promise (#6695)
This commit is contained in:
parent
03f28a7a1a
commit
bdbb70b49c
@ -8,7 +8,10 @@ jest.unmock('lodash')
|
||||
|
||||
jest.useFakeTimers()
|
||||
|
||||
const _mount = (payload = {}) =>
|
||||
const _mount = (
|
||||
payload = {},
|
||||
type: 'fn-cb' | 'fn-promise' | 'fn-arr' | 'arr' = 'fn-cb'
|
||||
) =>
|
||||
mount({
|
||||
setup() {
|
||||
const state = reactive({
|
||||
@ -22,19 +25,33 @@ const _mount = (payload = {}) =>
|
||||
payload,
|
||||
})
|
||||
|
||||
const querySearch = (
|
||||
queryString: string,
|
||||
cb: (arg: typeof state.list) => void
|
||||
) => {
|
||||
cb(
|
||||
queryString
|
||||
? state.list.filter(
|
||||
(i) => i.value.indexOf(queryString.toLowerCase()) === 0
|
||||
)
|
||||
: state.list
|
||||
)
|
||||
function filterList(queryString: string) {
|
||||
return queryString
|
||||
? state.list.filter(
|
||||
(i) => i.value.indexOf(queryString.toLowerCase()) === 0
|
||||
)
|
||||
: state.list
|
||||
}
|
||||
|
||||
const querySearch = (() => {
|
||||
switch (type) {
|
||||
case 'fn-cb':
|
||||
return (
|
||||
queryString: string,
|
||||
cb: (arg: typeof state.list) => void
|
||||
) => {
|
||||
cb(filterList(queryString))
|
||||
}
|
||||
case 'fn-promise':
|
||||
return (queryString: string) =>
|
||||
Promise.resolve(filterList(queryString))
|
||||
case 'fn-arr':
|
||||
return (queryString: string) => filterList(queryString)
|
||||
case 'arr':
|
||||
return state.list
|
||||
}
|
||||
})()
|
||||
|
||||
return () => (
|
||||
<Autocomplete
|
||||
ref="autocomplete"
|
||||
@ -134,6 +151,48 @@ describe('Autocomplete.vue', () => {
|
||||
expect(fetchSuggestions).toHaveBeenCalledTimes(2)
|
||||
})
|
||||
|
||||
test('fetchSuggestions with fn-promise', async () => {
|
||||
const wrapper = _mount({ debounce: 10 }, 'fn-promise')
|
||||
await nextTick()
|
||||
await wrapper.find('input').trigger('focus')
|
||||
jest.runAllTimers()
|
||||
await nextTick()
|
||||
|
||||
const target = wrapper.getComponent(Autocomplete).vm as InstanceType<
|
||||
typeof Autocomplete
|
||||
>
|
||||
|
||||
expect(target.suggestions.length).toBe(4)
|
||||
})
|
||||
|
||||
test('fetchSuggestions with fn-arr', async () => {
|
||||
const wrapper = _mount({ debounce: 10 }, 'fn-arr')
|
||||
await nextTick()
|
||||
await wrapper.find('input').trigger('focus')
|
||||
jest.runAllTimers()
|
||||
await nextTick()
|
||||
|
||||
const target = wrapper.getComponent(Autocomplete).vm as InstanceType<
|
||||
typeof Autocomplete
|
||||
>
|
||||
|
||||
expect(target.suggestions.length).toBe(4)
|
||||
})
|
||||
|
||||
test('fetchSuggestions with arr', async () => {
|
||||
const wrapper = _mount({ debounce: 10 }, 'arr')
|
||||
await nextTick()
|
||||
await wrapper.find('input').trigger('focus')
|
||||
jest.runAllTimers()
|
||||
await nextTick()
|
||||
|
||||
const target = wrapper.getComponent(Autocomplete).vm as InstanceType<
|
||||
typeof Autocomplete
|
||||
>
|
||||
|
||||
expect(target.suggestions.length).toBe(4)
|
||||
})
|
||||
|
||||
test('valueKey / modelValue', async () => {
|
||||
const wrapper = _mount()
|
||||
await nextTick()
|
||||
|
@ -38,8 +38,12 @@ export const autocompleteProps = buildProps({
|
||||
},
|
||||
fetchSuggestions: {
|
||||
type: definePropType<
|
||||
(queryString: string, cb: (data: any[]) => void) => void
|
||||
>(Function),
|
||||
| ((
|
||||
queryString: string,
|
||||
cb: (data: { value: string }[]) => void
|
||||
) => { value: string }[] | Promise<{ value: string }[]> | void)
|
||||
| { value: string }[]
|
||||
>([Function, Array]),
|
||||
default: NOOP,
|
||||
},
|
||||
popperClass: {
|
||||
|
@ -96,6 +96,7 @@ import {
|
||||
nextTick,
|
||||
useAttrs as useCompAttrs,
|
||||
} from 'vue'
|
||||
import { isPromise } from '@vue/shared'
|
||||
import { debounce } from 'lodash-unified'
|
||||
import { onClickOutside } from '@vueuse/core'
|
||||
import { useAttrs, useNamespace } from '@element-plus/hooks'
|
||||
@ -165,7 +166,7 @@ const getData = (queryString: string) => {
|
||||
return
|
||||
}
|
||||
loading.value = true
|
||||
props.fetchSuggestions(queryString, (suggestionsArg) => {
|
||||
const cb = (suggestionsArg: any[]) => {
|
||||
loading.value = false
|
||||
if (suggestionDisabled.value) {
|
||||
return
|
||||
@ -176,7 +177,17 @@ const getData = (queryString: string) => {
|
||||
} else {
|
||||
throwError(COMPONENT_NAME, 'autocomplete suggestions must be an array')
|
||||
}
|
||||
})
|
||||
}
|
||||
if (isArray(props.fetchSuggestions)) {
|
||||
cb(props.fetchSuggestions)
|
||||
} else {
|
||||
const result = props.fetchSuggestions(queryString, cb)
|
||||
if (isArray(result)) {
|
||||
cb(result)
|
||||
} else if (isPromise(result)) {
|
||||
result.then(cb)
|
||||
}
|
||||
}
|
||||
}
|
||||
const debouncedGetData = debounce(getData, props.debounce)
|
||||
const handleInput = (value: string) => {
|
||||
|
Loading…
Reference in New Issue
Block a user