Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Vue.Draggable delete item by dragging into designated region

I've been banging my head against the wall trying to figure this out. I found an example of pretty much exactly what I'm trying to do via the Sortable.js library repo here but I haven't been able to implement it using Vue.Draggable.

My theory of how to do it is add a <draggable/> element that is in the same group as the rest of the elements and listen for an @add event on it, then remove that dragged element from its list.

One gotcha (maybe) is I'm trying to designate a "trash" button as the removal region, and if it references the same draggable group, that dragged element gets appended to the button group and throws off the whole UI. So, a really important thing as that there's some sort of user feedback (e.g. trash icon turns red when hovering with drag element), but the dragged element shouldn't get inserted to the button group.

Initial Drag State

mouse cursor over the item to delete

Intended Delete Action

enter image description here

Thanks in advance!

like image 859
slowFooMovement Avatar asked Mar 05 '23 17:03

slowFooMovement


1 Answers

Lets solve some of the problems in turn:

How do I let a trash draggable accept any group

The answer to that is to set the pull and push of the group attribute.

  trashOptions: {
    group: {
      name: 'trash',
      draggable: '.dropitem',
      put: () => true,
      pull: false
    }
  }

By setting put to a function that always returns true, it will accept any group. Alternatively you can set it to an array with groups you accept from.

How do I prevent my button from being messed up when setting it as a draggable area

The easiest way is to set the inserted item to display: none. You can simply hide whatever you set as the draggable attribute, or use the ghostClass setting (as per the documentation).

How do I give the user feedback?

This one is tricky. Draggable does not set a class on the draggable area you are using. You can however use a smart css selector to sort-of achieve what you want. First we define a footer.

<draggable v-model="trashZone" class="dropzone trashzone" :options="trashOptions">
  <div slot="footer" class="footer">Trash</div>
</draggable>

We position this absolute to the dropzone and make sure it covers the entire thing. Dropped elements will now always appear before the footer. This is great, because we can use the next-selector (+) to select the footer after the inserted dropitem, and apply different styling. In this case we apply a red background and make the text white.

.trashzone .footer {
  display: block;
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
}

.trashzone .dropitem + .footer {
  background: red;
  color: white;
}

A full working example is available on codesandbox.

Edit Vue Template

like image 109
Sumurai8 Avatar answered Mar 09 '23 06:03

Sumurai8