diff --git a/packages/components/autocomplete/src/autocomplete.vue b/packages/components/autocomplete/src/autocomplete.vue
index ddcceab278e59..663ffbe79700b 100644
--- a/packages/components/autocomplete/src/autocomplete.vue
+++ b/packages/components/autocomplete/src/autocomplete.vue
@@ -14,6 +14,8 @@
:transition="`${ns.namespace.value}-zoom-in-top`"
persistent
@before-show="onSuggestionShow"
+ @show="onShow"
+ @hide="onHide"
>
@@ -100,7 +103,7 @@ import {
import { debounce } from 'lodash-unified'
import { onClickOutside } from '@vueuse/core'
import { Loading } from '@element-plus/icons-vue'
-import { useAttrs, useNamespace } from '@element-plus/hooks'
+import { useAttrs, useDisabled, useNamespace } from '@element-plus/hooks'
import { generateId, isArray, throwError } from '@element-plus/utils'
import {
CHANGE_EVENT,
@@ -130,6 +133,7 @@ const emit = defineEmits(autocompleteEmits)
const attrs = useAttrs()
const rawAttrs = useRawAttrs()
+const disabled = useDisabled()
const ns = useNamespace('autocomplete')
const inputRef = ref()
@@ -137,7 +141,7 @@ const regionRef = ref()
const popperRef = ref()
const listboxRef = ref()
-let isClear = false
+let ignoreFocusEvent = false
const suggestions = ref([])
const highlightedIndex = ref(-1)
const dropdownWidth = ref('')
@@ -155,6 +159,15 @@ const suggestionVisible = computed(() => {
const suggestionLoading = computed(() => !props.hideLoading && loading.value)
+const refInput = computed(() => {
+ if (inputRef.value) {
+ return Array.from(
+ inputRef.value.$el.querySelectorAll('input')
+ )
+ }
+ return []
+})
+
const onSuggestionShow = async () => {
await nextTick()
if (suggestionVisible.value) {
@@ -162,6 +175,15 @@ const onSuggestionShow = async () => {
}
}
+const onShow = () => {
+ ignoreFocusEvent = true
+}
+
+const onHide = () => {
+ ignoreFocusEvent = false
+ highlightedIndex.value = -1
+}
+
const getData = async (queryString: string) => {
if (suggestionDisabled.value) return
@@ -194,24 +216,34 @@ const handleInput = (value: string) => {
emit(UPDATE_MODEL_EVENT, value)
suggestionDisabled.value = false
- activated.value ||= isClear && valuePresented
+ activated.value ||= valuePresented
if (!props.triggerOnFocus && !value) {
suggestionDisabled.value = true
suggestions.value = []
return
}
- if (isClear && valuePresented) {
- isClear = false
- }
+
debouncedGetData(value)
}
+const handleMouseDown = (event: MouseEvent) => {
+ if (disabled.value) return
+ if (
+ (event.target as HTMLElement)?.tagName !== 'INPUT' ||
+ refInput.value.includes(document.activeElement as HTMLInputElement)
+ ) {
+ activated.value = true
+ }
+}
+
const handleChange = (value: string) => {
emit(CHANGE_EVENT, value)
}
const handleFocus = (evt: FocusEvent) => {
+ if (ignoreFocusEvent) return
+
activated.value = true
emit('focus', evt)
if (props.triggerOnFocus) {
@@ -220,12 +252,12 @@ const handleFocus = (evt: FocusEvent) => {
}
const handleBlur = (evt: FocusEvent) => {
+ if (ignoreFocusEvent) return
emit('blur', evt)
}
const handleClear = () => {
activated.value = false
- isClear = true
emit(UPDATE_MODEL_EVENT, '')
emit('clear')
}
@@ -239,7 +271,6 @@ const handleKeyEnter = async () => {
handleSelect(suggestions.value[highlightedIndex.value])
} else if (props.selectWhenUnmatched) {
emit('select', { value: props.modelValue })
- await nextTick()
suggestions.value = []
highlightedIndex.value = -1
}
@@ -265,7 +296,6 @@ const handleSelect = async (item: any) => {
emit(INPUT_EVENT, item[props.valueKey])
emit(UPDATE_MODEL_EVENT, item[props.valueKey])
emit('select', item)
- await nextTick()
suggestions.value = []
highlightedIndex.value = -1
}
@@ -305,7 +335,9 @@ const highlight = (index: number) => {
)
}
-onClickOutside(listboxRef, close)
+onClickOutside(listboxRef, () => {
+ suggestionVisible.value && close()
+})
onMounted(() => {
// TODO: use Volar generate dts to fix it.