Alfred-Skyblue / vue-draggable-plus

Universal Drag-and-Drop Component Supporting both Vue 3 and Vue 2
https://vue-draggable-plus.pages.dev/en/
MIT License
2.72k stars 106 forks source link

can receive new elements from another list #65

Closed luisrossi closed 6 months ago

luisrossi commented 7 months ago

Would it be possible to define in a list whether or not it can receive new elements from another list? I have a use case where I have 18 lists that allow a single element or no elements. And another with several elements. I need to be able to drag the elements of these 18 lists between them, however, without allowing two items to be in the same list.

The onMove method returning false does not solve this problem.

The application is vue 2.7

Furthermore, are you interested in implementing documentation in PT? I can help with that

Alfred-Skyblue commented 7 months ago

Only the same groups can drag each other. If the group names are the same, they can accept dragging elements from each other. If they are different, they cannot.

Furthermore, are you interested in implementing documentation in PT? I can help with that

I don't quite understand what you mean. Can you elaborate? Thanks.

luisrossi commented 6 months ago

I have 18 lists, all of them allow dragging. I can drag between lists. However, I need to validate that the list to receive the new item is empty, if there is already another item in the list, it should not allow it. Is this possible somehow?

Furthermore, I noticed that the documentation only has translations in English and Mandarin. If you are interested, I can try to help with the translation into Portuguese

Alfred-Skyblue commented 6 months ago

I have 18 lists, all of them allow dragging. I can drag between lists. However, I need to validate that the list to receive the new item is empty, if there is already another item in the list, it should not allow it. Is this possible somehow?

When a list is not empty, you should either use the option/pause method to pause it, or set its group so that it can or cannot interact with other lists.

Furthermore, I noticed that the documentation only has translations in English and Mandarin. If you are interested, I can try to help with the translation into Portuguese

Maintaining documentation for multiple versions increases our workload and complicates our documentation. It means that every time we add a new feature, we have to maintain documentation for multiple versions, which can be a very painful task. Of course, you can create a repository to manage documentation for respective versions, and we would greatly appreciate it if you do so.

gedrick commented 4 months ago

I'm going to bump this issue because it's still ongoing.

I have a list and within the list can be a group with another list. Something like this structure:

What I am trying to do is prevent someone from dragging Group A into Group B, or vice verse. But, I still want Item A and Item B to be able to be dragged into either group. Just not a group into another group. Therefore, all 3 draggable instances (top level, Group A, and Group B) need to have the same group.

Sortablejs had the @move handler that you could optionally return false to prevent a certain move. This functionality does not seem to exist in this library at the present time.

gedrick commented 4 months ago

OK, I finally got this working after some trial and error. First I had to change my implementation from component to useDraggable. This was fairly simple.

Next, for each list item that you are iterating over via a v-for=field in fields, add a data attribute. In my case I used this:

:data-draggable-group="isGroupModel(field)"

This either equates to true or false. We are going to use this data attribute to check if we're dragging into a group, and then check if the current dragged element is also a group, and then prevent the drag if that is true. The next part is where you can add whichever logic you need to make sure the user can indeed drop into the current list.

In the onMove event, this is the logic I have:

const onMove = (event: MoveEvent): boolean => {
  // if you try and move a group into another group, prevent the drag operation
  const from = event.dragged.dataset.draggableGroup // this will be true if the current dragged item is a group.
  const to = event.to.parentElement?.parentElement?.dataset.draggableGroup // same here, but for the target.
  if (from && to) { // if you're dragging a group into a group....
    draggableElement.pause() // draggableElement is the return value from `useDraggable()` - pause the drag.
    return false
  }
  return true
}

This will pause dragging completely and prevent the drop.

Lastly, in the onEnd handler, simply put draggableElement.resume().

In the case of @luisrossi , you can change this onMove handler to instead check the length of the current list and make sure it's 0. Otherwise, pause the dragging and return false.