Quasar: QMenu closing when an element clicked inside it is removed from the DOM

Created on 3 Apr 2020  路  5Comments  路  Source: quasarframework/quasar

Describe the bug
When a component like a QItem with the clickable prop or a QChip with the removable prop is clicked inside a QMenu and, as a result of that click, the QItem or QChip clicked is removed from the DOM, the QMenu is closed.

When one of the described inner elements is clicked, they send a focusin event. Specifically, a clickable QItem inside a QList calls the focus() method on the $refs.blurTarget element. The click-outside directive applied to the QMenu, which is listening to the focusin event, executes the handler to close the QMenu with a timeout of 200ms. If the click event removes the element from the DOM, that timeout means the target of the focus event is not found inside the QMenu anymore when the handler is run, and this makes the QMenu close.

I have tried to circumvent this behavior in a few different ways.

  • Making the QMenu persistent works, as it does not apply the click-outside directive to it, but I do want to be able to hide it when I do actually click outside of it.
  • Trying to set my own click-outside directive in the QMenu doesn't work, as it gets overridden by the render function of the QMenu component.
  • Making the list items not clickable, listening to the native click event on them and manually focusing them works, but it's kind of an ugly solution and I don't find an alternative for removable QChips, as the 'remove' event is not native.

Codepen/jsFiddle/Codesandbox (required)
https://jsfiddle.net/cto4q5gf/14/

To Reproduce
Steps to reproduce the behavior:

  1. Go to https://jsfiddle.net/cto4q5gf/14/
  2. Click on "Open Menu"
  3. Inside the menu, there is just a text to show a QLIst: "Open list of items". Click on it. A list appears inside the menu.
  4. Click on any of the list items. This should just hide the list, but it also closes the QMenu

Expected behavior
The list inside the menu should hide, but the menu should still remain open.

Platform (please complete the following information):
OS: MacOs
Node: v13.11.0
Yarn: 1.22.4
Browsers: Chrome 80.0.3987.149

Additional context
Quasar v1.9.3

bug

All 5 comments

You can:

  • use v-show instead of v-if for menu
  • hide the list after focusing another element in the menu

Hey @pdanpdan, thank you so much for your help, really appreciate it.

Regarding your solutions:

  • I did think of just hiding the element, but my example is a simplified scenario. In my real example, choosing an element of the list changes a computed property that changes the list, so it doesn't matter whether I hide the items or not, the click on an item renders a different list and the dom element will be removed no matter what. Here's a jsfiddle closer to my real use case: https://jsfiddle.net/w4nh7vmq/8/. Of course, I can tweak my javascript code to achieve not removing the rendered list until all the handlers for the click and input events have been processed, but that would require me to make my component logic way more complex, and that's what I'm trying to avoid.
  • I'm not sure I follow when you tell me to focus another element in the menu. Would that work for itself? I mean, it doesn't really prevent the current focus listener to be run in the click-outside directive because the focus() function is called in the QItem even if I also call it somewhere else. I tried focusing something else in my updated jsfiddle (https://jsfiddle.net/w4nh7vmq/8/) but I see the problematic flow still being reproduced. What you say sounds good, could I bother you to please elaborate it so I can try and fix it this way?

ou must put a tabindex attr on the element you want to focus: https://jsfiddle.net/yo3fwxad/7/

And that did the trick! It's working as expected now. Thanks a lot, @pdanpdan, really appreciate your help.

I think we should close this - it's nothing I can think of that we can do at framework level.
If anybody has an idea please post here.

Was this page helpful?
0 / 5 - 0 ratings