Skip to content

Commit

Permalink
fix(components): fix iOS select click event listening
Browse files Browse the repository at this point in the history
iOS Safari does not handle click events when a mouseenter event is registered and a DOM-change
happens in a child. We use a Vue custom event binding to only register the event on non-iOS devices.
The inputHovering state gets updated now on iOS-devices on click. This is needed as the mouseenter
event normally does this.

closed element-plus#5210
  • Loading branch information
rb-clubdrei committed Apr 4, 2024
1 parent 22ac4c5 commit b74aeea
Show file tree
Hide file tree
Showing 2 changed files with 13 additions and 1 deletion.
2 changes: 1 addition & 1 deletion packages/components/select/src/select.vue
Expand Up @@ -3,7 +3,7 @@
ref="selectRef"
v-click-outside:[popperRef]="handleClickOutside"
:class="[nsSelect.b(), nsSelect.m(selectSize)]"
@mouseenter="states.inputHovering = true"
@[mouseEnterEventName]="states.inputHovering = true"
@mouseleave="states.inputHovering = false"
@click.prevent.stop="toggleMenu"
>
Expand Down
12 changes: 12 additions & 0 deletions packages/components/select/src/useSelect.ts
Expand Up @@ -28,6 +28,7 @@ import {
debugWarn,
isClient,
isFunction,
isIOS,
isNumber,
isUndefined,
scrollIntoView,
Expand Down Expand Up @@ -253,6 +254,12 @@ export const useSelect = (props: ISelectProps, emit) => {
: states.selectedLabel
})

// iOS Safari does not handle click events when a mouseenter event is registered and a DOM-change happens in a child
// We use a Vue custom event binding to only register the event on non-iOS devices
// ref.: https://developer.apple.com/library/archive/documentation/AppleApplications/Reference/SafariWebContent/HandlingEvents/HandlingEvents.html
// Github Issue: https://github.com/vuejs/vue/issues/9859
const mouseEnterEventName = computed(() => (isIOS ? null : 'mouseenter'))

watch(
() => props.modelValue,
(val, oldVal) => {
Expand Down Expand Up @@ -670,6 +677,10 @@ export const useSelect = (props: ISelectProps, emit) => {
const toggleMenu = () => {
if (selectDisabled.value) return

// We only set the inputHovering state to true on mouseenter event on iOS devices
// To keep the state updated we set it here to true
if (isIOS) states.inputHovering = true

if (states.menuVisibleOnFocus) {
// controlled by automaticDropdown
states.menuVisibleOnFocus = false
Expand Down Expand Up @@ -814,6 +825,7 @@ export const useSelect = (props: ISelectProps, emit) => {
hasModelValue,
shouldShowPlaceholder,
currentPlaceholder,
mouseEnterEventName,
showClose,
iconComponent,
iconReverse,
Expand Down

0 comments on commit b74aeea

Please sign in to comment.