tusen-ai / naive-ui

A Vue 3 Component Library. Fairly Complete. Theme Customizable. Uses TypeScript. Fast.
https://www.naiveui.com
MIT License
16.2k stars 1.67k forks source link

`<n-dropdown trigger="focus"/>`鼠标点击不会触发select事件 #4335

Closed heroboy closed 8 months ago

heroboy commented 1 year ago

TuSimple/naive-ui version (版本)

2.34.3

Vue version (Vue 版本)

3.2.45

Browser and its version (浏览器及其版本)

Chrome

System and its version (系统及其版本)

Window 10

Node version (Node 版本)

Reappearance link (重现链接)

https://codesandbox.io/s/upbeat-http-e58t57?file=/src/Demo.vue

Reappearance steps (重现步骤)

点上面的minimal reproduction。 鼠标点一下文本框,然后点一下任何一个菜单项。

Expected results (期望的结果)

弹出message,表示触发的select事件。

Actual results (实际的结果)

什么都没发生,只是菜单消失了。

Remarks (补充说明)

不使用文本框,使用按钮也是一样有这个bug的。 使用键盘上下选择,回车确认是会触发select事件的。

thibodeauxjl commented 1 year ago

I'm not sure this is a bug. Looking through the documentation, available triggers are "click" and "hover". If you want it explicitly on focus, you would need the following:

<n-dropdown :show="showDropdown" @select="handleSelect">
  <n-input @focus="handleFocus" />
</n-dropdown>

You will also need to import 'ref' from Vue

import { defineComponent, ref } from 'vue'

Declare a reference to showDropdown

const showDropdown = ref(false)

Include showDropdown in the return and define the following functions after your options.

handleSelect(key) {
  message.info(String(key));
  showDropdown.value = false;
}

handleFocus() {
  showDropdown.value = !showDropdown.value
}

If you wanted to use the NButton component, you could set trigger="hover" or trigger="click" or manually as above.

heroboy commented 1 year ago

hello @thibodeauxjl, In the popover document, the trigger type is 'hover' | 'click' | 'focus' | 'manual'(and same in the .d.ts file ). So in your example you should set trigger prop to manual.

And I have already tried your example that explicitly set the show prop in the focus/blur events. The bug still occurs.

thibodeauxjl commented 1 year ago

https://codesandbox.io/s/laughing-paper-ld4jei?file=/src/Demo.vue

That is correct, but you are currently using a Dropdown.. not a popover, so not all the props for a popover are compatible and the documentation isn't real clear on which ones are or aren't. The only one it specifies is 'placement' under the Dropdown Props documentation.

heroboy commented 1 year ago

Maybe I know what's the problem here. When user click the menu item:

  1. input blur .
  2. dropdown receive the blur event, and set show = false
  3. menu item being clicked
  4. because the dropdown show == false, so it ignores the click event

@thibodeauxjl

That is correct, but you are currently using a Dropdown.. not a popover, so not all the props for a popover are compatible and the documentation isn't real clear on which ones are or aren't. The only one it specifies is 'placement' under the Dropdown Props documentation.

The document says For other props, for example placement, and the trigger is not in the above. So it is other props.

In your example, you doesn't handle blur event, so the dropdown remains showing when click outside the control. And because you toggle the boolean variable in focus event, the dropdown will hide when the input focus again. This is so bad use experience.

thibodeauxjl commented 1 year ago

There is a dropdown prop for on-clickoutside. I've updated the above codesandbox to handle the @clickoutside. I'm not exactly sure what you are trying to accomplish. If you need a simple dropdown when the user clicks the input or the button, then trigger="click" will do that. If you looking for some advanced functionality then please explain what exactly it is you are looking for and I'll try my best to help you out with it.

thibodeauxjl commented 1 year ago

After testing them all, the best user experience would be on-focus and on-blur. Click functionality seems to repeat every time its been clicked. on-clickoutside disappears with a double click.

<n-dropdown :show="showDropdown" :options="options" @select="handleSelect">
    <n-input @focus="handleFocus" @blur="handleBlur" />
</n-dropdown>

You'll set value of showDropdown to true on focus and false on blur.

heroboy commented 1 year ago

There is a dropdown prop for on-clickoutside. I've updated the above codesandbox to handle the @clickoutside. I'm not exactly sure what you are trying to accomplish. If you need a simple dropdown when the user clicks the input or the button, then trigger="click" will do that. If you looking for some advanced functionality then please explain what exactly it is you are looking for and I'll try my best to help you out with it.

In the example, use tab navigate one input to another, the menu is not disappear.

heroboy commented 1 year ago

You'll set value of showDropdown to true on focus and false on blur.

As I said above, blur event fired first, the menu item click may be ignored.

thibodeauxjl commented 1 year ago

I'm seeing the dilemma now. Give me a couple minutes.

thibodeauxjl commented 1 year ago

I've updated the link above again with the auto complete component which works really well with the input functionality you are looking for.

I think it would still be beneficial if they would add a on-mousedown prop for the focus trigger on the dropdown though. Possible feature request?

heroboy commented 1 year ago

和这个bug无关,我想说说我的需求。 我想要一个文本框,输入的内容是从一个固定的内容中选择的。例如:输入固定的几十种颜色。

根据这个需求的描述,首选肯定是一个Select。但是,Select的缺点是,它不是文本框,它没有文本框的各种方便特性。不能在极少数的情况下输入自定义内容(fiilterable,on-create可以,但是不好,不能基于当前选中的文本修改,而要完全重新输入。可能自定义输入的内容还会追加到当前列表,这点不好)。Select最大的不好在于,不能复制粘贴内容,这其实非常不方便。

我还试过AutoComplete。一开始我以为要有内容输入才会弹出候选列表,示例里每个都是。我试过才知道,focus的时候列表就能显示出来了。它的问题是,当列表弹出来的时候,没能自动滚动和选中当前的那一条。还是一个问题是,只在focus的时候弹出列表,选择了一个之后,列表消失,要在外面点一下,在点一下文本框列表才显示出来。不过这个问题后来我想到可以在on-select事件中,直接调用blur()来解决。

最后是当前bug的方案,Input+Dropdown。我比较想使用这个方案,在我心底就希望它是个文本框并且在focus的时候弹出候选列表。但是出来有当前的bug外,还有AutoComplete不能自动选中的问题,还有就是列表太长是没有滚动条的,会把页面拉长。

我觉得我还是会选择Select,全程鼠标操作的话,Select的体验还是最好的。

heroboy commented 1 year ago

I've updated the link above again with the auto complete component which works really well with the input functionality you are looking for.

I think it would still be beneficial if they would add a on-mousedown prop for the focus trigger on the dropdown though. Possible feature request?

Thanks you. You demo is perfect to solve my orginal request. But finally I choose to use Select, becuase my candidate items are so much that dropdown will enlarge the body with a scrollbar. And Select's popover itself has a scrollbar.

And I think the bug is still there, if I doesn't guess wrong in the https://github.com/tusen-ai/naive-ui/issues/4335#issuecomment-1378447803

thibodeauxjl commented 1 year ago

The bug is due to the @click event taking place after mouseup in the event cycle. The @blur event takes place after mousedown in the event cycle. Because of this, the @click never happens as it occurs after the dropdown is hidden. Which is why I mentioned a possible on-mousedown prop to work with the focus trigger.

jahnli commented 8 months ago

This issue does not have any recent activity. If you are still experiencing similar problems, open a new error, including a minimal copy of the problem