diff --git a/packages/select-v2/__tests__/select.spec.ts b/packages/select-v2/__tests__/select.spec.ts index ca74c9f110..b39b69132e 100644 --- a/packages/select-v2/__tests__/select.spec.ts +++ b/packages/select-v2/__tests__/select.spec.ts @@ -26,6 +26,7 @@ interface SelectProps { disabled?: boolean clearable?: boolean multiple?: boolean + filterable?: boolean multipleLimit?: number [key: string]: any } @@ -34,6 +35,8 @@ interface SelectEvents { onChange?: (value?: string) => void onVisibleChange?: (visible?: boolean) => void onRemoveTag?: (tag?: string) => void + onFocus?: (event?: FocusEvent) => void + onBlur?: (event?) => void [key: string]: (...args) => any } @@ -48,10 +51,13 @@ const createSelect = (options: { :disabled="disabled" :clearable="clearable" :multiple="multiple" + :filterable="filterable" :multiple-limit="multipleLimit" @change="onChange" @visible-change="onVisibleChange" @remove-tah="onRemoveTag" + @focus="onFocus" + @blur="onBlur" v-model="value"> `, { data () { @@ -62,6 +68,7 @@ const createSelect = (options: { disabled: false, clearable: false, multiple: false, + filterable: false, multipleLimit: 0, ...options.data && options.data(), } @@ -70,6 +77,8 @@ const createSelect = (options: { onChange: NOOP, onVisibleChange: NOOP, onRemoveTag: NOOP, + onFocus: NOOP, + onBlur: NOOP, ...options.methods, }, }) @@ -381,4 +390,69 @@ describe('Select', () => { expect(vm.value.length).toBe(2) }) }) + + describe('event', () => { + + it('focus & blur', async () => { + const onFocus = jest.fn() + const onBlur = jest.fn() + const wrapper = createSelect({ + methods: { + onFocus, + onBlur, + }, + }) + const input = wrapper.find('input') + const select = wrapper.findComponent(Select) + await input.trigger('focus') + // Simulate focus state to trigger menu multiple times + select.vm.toggleMenu() + await nextTick + select.vm.toggleMenu() + await nextTick + // Simulate click the outside + select.vm.handleClickOutside() + await nextTick + expect(onFocus).toHaveBeenCalledTimes(1) + expect(onBlur).toHaveBeenCalled() + }) + + it('focus & blur for multiple & filterable select', async () => { + const onFocus = jest.fn() + const onBlur = jest.fn() + const wrapper = createSelect({ + data() { + return { + multiple: true, + filterable: true, + value: [], + } + }, + methods: { + onFocus, + onBlur, + }, + }) + const input = wrapper.find('input') + const select = wrapper.findComponent(Select) + await input.trigger('focus') + // Simulate focus state to trigger menu multiple times + select.vm.toggleMenu() + await nextTick + select.vm.toggleMenu() + await nextTick + // Select multiple items in multiple mode without triggering focus + const options = getOptions() + options[1].click() + await nextTick + options[2].click() + await nextTick + expect(onFocus).toHaveBeenCalledTimes(1) + // Simulate click the outside + select.vm.handleClickOutside() + await nextTick + await nextTick + expect(onBlur).toHaveBeenCalled() + }) + }) }) diff --git a/packages/select-v2/src/useSelect.ts b/packages/select-v2/src/useSelect.ts index d128a1249e..802ab8e794 100644 --- a/packages/select-v2/src/useSelect.ts +++ b/packages/select-v2/src/useSelect.ts @@ -221,8 +221,8 @@ const useSelect = (props: ExtractPropTypes, emit) => { // if (expanded.value) { // expanded.value = false // } + if (states.isComposing) states.softFocus = true expanded.value = !expanded.value - states.softFocus = true inputRef.value?.focus?.() // } } @@ -388,14 +388,9 @@ const useSelect = (props: ExtractPropTypes, emit) => { states.selectedLabel = option.label update(option.value) expanded.value = false + states.isComposing = false + states.isSilentBlur = byClick } - states.isComposing = false - states.isSilentBlur = byClick - // setSoftFocus() - if (expanded.value) return - nextTick(() => { - // scrollToOption(option) - }) } const deleteTag = (event: MouseEvent, tag: Option) => { @@ -423,15 +418,14 @@ const useSelect = (props: ExtractPropTypes, emit) => { } const handleFocus = (event: FocusEvent) => { + const focused = states.isComposing states.isComposing = true if (!states.softFocus) { if (props.automaticDropdown || props.filterable) { expanded.value = true - // if (props.filterable) { - // states.menuVisibleOnFocus = true - // } } - emit('focus', event) + // If already in the focus state, shouldn't trigger event + if (!focused) emit('focus', event) } else { states.softFocus = false } @@ -444,7 +438,6 @@ const useSelect = (props: ExtractPropTypes, emit) => { } } - states.isComposing = false states.softFocus = false // reset input value when blurred @@ -454,7 +447,6 @@ const useSelect = (props: ExtractPropTypes, emit) => { if (calculatorRef.value) { states.calculatedWidth = calculatorRef.value.getBoundingClientRect().width } - if (states.isSilentBlur) { states.isSilentBlur = false } else { @@ -462,6 +454,7 @@ const useSelect = (props: ExtractPropTypes, emit) => { emit('blur') } } + states.isComposing = false }) }