The Issue
I'm using SortableJS to build a draggable tree component. Which means each of my sortable-item
s has a toggle-arrow
as a child element that opens and closes a sub-tree
(if there is one).
I'm attempting to use stopPropagation()
to prevent the selection of the parent sortable-item
if the toggle-arrow
is clicked, but it's not working.
It looks like this when closed:
And looks like this when open:
The blue highlight you see in the open state (the second image) is the styling I've chosen for the selectedClass
option when using the multiDrag
plugin.
This is illustrating that when I click on the toggle-arrow
it results in the parent sortable-item
being selected.
I don't want this to happen.
The Code
The code for an item in my SortableJS tree component looks like so (using Vue.js, and Pug syntax):
div.sortable-item
div.content
div.toggle-arrow(@click.stop="toggleTree($event)")
div.icon
div.title
div.sub-tree
And then I've got a handler for the @click
binding on my toggle-arrow
element:
toggleTree = function($event) {
$event.stopPropagation()
/// Code for handling the sub-tree toggling goes here.
/// The sub-tree toggling itself works just fine.
}
You can see that I'm declaring @click.stop
as the event binding, which should stop the click
event from bubbling up from the toggle-arrow
child element, but it's not working.
I'm even attempting to use $event.stopPropagation
within the handler. But, the event seems to continue to bubble, and thus the parent sortable-item
element ends up in a selected state.
I've also tried declaring @click.native.stop
as the event binding, but it simply prevents my toggleTree
method from firing at all. I'm assuming there's another event handler somewhere within SortableJS
that's interfering with the @click.native.stop
binding.
Questions
How do I stop propagation of an event when a child element of my sortable-item
is clicked?
How is selection handled by the multiDrag
plugin? I dug through the code and saw that the select
event is fired within the handler of the drop
event of the sortable-item
, but I'm confused by that. Why is the drop
event handler being used to toggle selection of a sortable-item
?
Thanks in advance for any light you may be able to shed on this.
Wrong Event
Looking at the source of SortableJS it seems that the event you want to stop from bubbling is not the click
event, but rather the mouseup
event.
The "Stuck" Drag Item Problem
As indicated in the comments of this answer, stopping propagation on the mouseup
event causes an issue where the drag is started unintentionally, and the sortable-item
becomes "stuck" to the pointer.
It seems that the "drag initiation" is triggered by either pointerdown
, mousedown
, or touchstart
events, depending on the device.
It can be safely assumed that the pointerdown
event is the one that does the triggering according to caniuse.com.
The Solution
So the actual way to solve this is to use a @pointerdown.stop
event binding to trigger your toggleTree
method without triggering either selection of the sortable-item
, or the unintentional drag initiation.
div.sortable-item
div.content
div.toggle-arrow(@pointerdown.stop="toggleTree($event)")
div.icon
div.title
div.sub-tree