2

I got a parent element containing an input:

<div @blur="onLeaveSelect($event)">
    <div v-if="searchActivated" >
        <input type="text" placeholder="Search..." @mousedown.stop>
    </div>
    ...
</div>

When now clicking on the input child element the blur event of the parent div is fired. How'd I prevent that behavior? Using click.stop to prohibit bubbling works for other elements, but not that input.

        const onLeaveSelect = (evt) => {
            if (!evt.currentTarget.contains(evt.relatedTarget)) {
                open.value = false;
                showDescription.value = false;
                searchActivated.value = false;
            }
        }

Like this I stopped the dropdown from closing by a click on the input event. But the problem now is that focusing the input counts as not focusing the parent div anymore, what prevents the blur from getting detected completely.

5
  • why is the blur there (what is its purpose/intention)?
    – depperm
    Commented Apr 7, 2022 at 12:51
  • @depperm It's used for closing a dropdown menu.
    – user8472012
    Commented Apr 7, 2022 at 12:53
  • why not place that closer to the dropdown menu?
    – depperm
    Commented Apr 7, 2022 at 12:54
  • @depperm I don't quite get what you mean. The div with the blur event includes the whole dropdown for easy closing it on a click outside.
    – user8472012
    Commented Apr 7, 2022 at 12:55
  • can you include the whole div content and include the expected behavior?
    – depperm
    Commented Apr 7, 2022 at 13:12

4 Answers 4

6

I wanted the same behavior. But the focusout event is not present in React.

The way I solved it is using the onBlur event with a check to see if any child element is the relatedTarget:

  • If it's null, a child element hasn't been clicked on (so, we will want to hide the drop-down)
  • If it's not null, a child element has been clicked on (this will prevent the drop-down from being hidden)

Code snippet showing the parent div:

<div
    tabIndex='-1'
    onBlur={e => e.relatedTarget === null && setState(false)}
>
...
</div>
2
  • 2
    Gave you +1 for the nice solution. but it is not working for me (maybe bc my child element is absolute) Commented Oct 23, 2022 at 17:58
  • Hi @codingnighter2000 It does not work because relatedTarget might choose entire page. You will need to stop the propogation at the certain point. Commented Apr 1 at 18:43
4

The solution for all of my problems was the focusout event. It also detects focus inside an input child element. focusout

0
1

That happens because of events bubbling so that they get propagated to the parents.

There's an interesting question here on SO that I happened to hit very often in the past: How to stop propagating event from parent div to child div

There are several ways to stop such propagation but probably the easiest to achieve in this case is to use the css attribute on your child element:

pointer-events: none;

But since you clearly need that input to fire events, maybe you could try this other option in the event handler you added to parent element:

  if(event.target !== event.currentTarget) return;

But if yet you can't achieve what you are aiming to, you may try this line inside the handler for the event you wish it didn't propagate to the parent element:

 event.stopPropagation();

And as a side note I realized that div are not used to have the blur event because they don't capture focus as long as they don't have any tabindex="0" or contentEditable attributes. Maybe that's set by that directive when it will render the real html.

2
  • But like this it also ain't possible to focus the input anymore cuase I got no pointer events at all. And chaning the values for the input and it's surrounding div ddin't do the trick.
    – user8472012
    Commented Apr 7, 2022 at 13:08
  • With the other option I'm just checking if the parent element itself is clicked. But cause it's a blur event I want it to fire when not clicking the element itself. It's tricky...
    – user8472012
    Commented Apr 7, 2022 at 13:16
-1

This is called event bubbling, to stop the event propagations, use e.stopPropagation() method on the child onClick()