Vue.Draggable: Dragging out of a transition-group to another draggable item causes visible blip

If I have two draggable lists, each with a <transition-group>, for Eexample:

List 1
<draggable>
  <transition-group>
    <card></card>
    <card></card>
    <card></card>
  </transition-group>
</draggable>

List 2
<draggable>
  <transition-group>
    <card></card>
    <card></card>
    <card></card>
  </transition-group>
</draggable>

…and I drag from one list to the other, the item I removed from the source list momentarily reappears before disappearing again.

In my app, the blip lasts a few hundred ms. I’ve ruled out transition timings, or waiting on DB persistence as an issue.

draggable-glitch-my-app

Here is a jsFiddle showing the problem: https://jsfiddle.net/jonathanheron/p07dmnso/

List 2 is wrapped in a transition group in this jsFiddle, but not List 1. Note the blip in List 2 when Item 1 is dragged to List 1

draggable-glitch

About this issue

  • Original URL
  • State: closed
  • Created 7 years ago
  • Comments: 17 (5 by maintainers)

Most upvoted comments

If it can help, i found a reasonable workaround to this. I added a onAdd event listener on both columns (<draggable> components), and set a class which set a display: none; to the dragged HTMLElement.

As a result, the element is not displayed anymore in the DOM before Vue updates the two lists, therefore the “visible blip” vanishes.

<draggable @add="onAdd">

onAdd (e) { e.item.classList.add('display-none') }

.display-none { display: none; }

The result before the workaround:

before

The result after the workaround:

after

@David-Desmaisons I’ve found a workaround:

  1. Have two copies of the list, only one of which is shown at any time:
  • The real, draggable list, with a transition-group
  • A fake list, rendered from the same data, but with no transition-group or draggable component
  1. When an item is removed and the remove event fires, swap over to the fake list — thus masking the transition-group blip.
  2. Once the transition-group’s after-leave event fires, swap back to the real list — making the list interactive again.

Here’s a fiddle showing it in action: https://jsfiddle.net/jonathanheron/qpv1qLpr/

And a GIF:

fix for blip

I have set a 1 second transition duration to make it clear that Show fake, static list: false changes to true, then back again. It works just as well when there’s an instant transition.

I’ve checked this in my app, which is doing server updates, reloading data, and making much more expensive DOM and painting updates — it works just as a well 😃

@jonathanheron , Here is how vuedraggable works:

  1. During the dragging it lets Sortable do the job updating DOM and so on
  2. After the dragging it reverts sortable modification on the DOM and update the array(s) acording the drag operation
  3. It let vue do the DOM updates reflecting the array changes that were done in 2)

This allows:

  1. to update the collection only when drags ends which corresponds to a user transaction
  2. Most importantly to make sure that Sortable and Vue will work nicely together, avoiding that both update the DOM at the same time

In the jsfiddle you created, there is a small moment after step 2 where the DOM element corresponding to the removed element is not removed by Vue. This linked to the transition-group. I am still trying to figure out if there is a way to work-around this.