SortableJS / vue.draggable.next

Vue 3 compatible drag-and-drop component based on Sortable.js
https://sortablejs.github.io/vue.draggable.next/#/simple
MIT License
3.91k stars 531 forks source link

Add Multidrag and Swap plugin support #153

Open david-mohr opened 2 years ago

david-mohr commented 2 years ago

Big thanks to @divinespear for the original Multidrag support in vue.draggable (https://github.com/SortableJS/Vue.Draggable/pull/1052).

I've ported it to Vue 3 (vue.draggable.next). I've also added support for the Swap plugin!

david-mohr commented 2 years ago

@Trojan0523 are you able to provide some code or a jsbin sample that shows the error? I have not seen either of these errors during my testing or production use.

Trojan0523 commented 2 years ago

@david-mohr sorry for that, i mount multiDrag plugin in my component twice, it`s my fault, your code is fully successful, thumbs up

rasmus0201 commented 2 years ago

Any progress on this? Looking forward to be able to use the :swap="true" prop! :)

david-mohr commented 2 years ago

I haven't had any feedback from the maintainers. Perhaps @David-Desmaisons could please take a look?

YahorDanchanka commented 2 years ago

When swap=true the animation property (on draggable component) does not work.

<draggable
    class="board"
    v-model="boardState"
    item-key="id"
    :swap="true"
    :animation="300"
  >
    <template #item="{ element, index }">
      <div class="board__letter">
        {{ element }}
      </div>
    </template>
  </draggable>
david-mohr commented 2 years ago

@YahorDanchanka It looks like all the animation logic is being applied, so it must be something to do with the way I handle the HTML elements. I'll try to find some time next week to see if I can fix it

david-mohr commented 2 years ago

@YahorDanchanka I've investigated the animation issue and I think I have a solution. Could you please try this out and see if it addresses your use case?

https://github.com/david-mohr/vue.draggable.next/tree/animation

Please note, this is an incomplete update, I'm just testing a theory on how vue and sortable interact

YahorDanchanka commented 2 years ago

Unfortunately, it doesn't work for me. My draggable state: [ { "value": "l" }, { "value": "e" }, { "value": "q" }, { "value": "x" }, { "value": "e" }, { "value": "s" }, { "value": "" }, { "value": "n" }, { "value": "" }, { "value": "a" }, { "value": "t" }, { "value": "t" }, { "value": "l" }, { "value": "r" }, { "value": "a" }, { "value": "o" }, { "value": "" }, { "value": "o" }, { "value": "" }, { "value": "p" }, { "value": "e" }, { "value": "i" }, { "value": "u" }, { "value": "i" }, { "value": "l" } ] Component params:

<draggable
        class="board"
        v-model="puzzleLinear"
        itemKey="id"
        :swap="true"
        :animation="300"
      >
        <template #item="{ element }">
          <div class="board__letter">{{ element.value }}</div>
        </template>
      </draggable>

From package.json url of vuedraggable: "vuedraggable": "https://github.com/david-mohr/vue.draggable.next.git#animation"

david-mohr commented 2 years ago

@YahorDanchanka you're missing a unique identifier per object (the itemKey). I'm fairly sure this is part of the issue.

david-mohr commented 2 years ago

@YahorDanchanka ah, sorry, my fault. I forgot to compile the code before pushing it. Could you please pull the latest version and try agian? If that still doesn't work, I'll spin up a more comprehensive test.

YahorDanchanka commented 2 years ago

-> you're missing a unique identifier per object (the itemKey). I'm fairly sure this is part of the issue. I have a Symbol('id') as id -> ah, sorry, my fault. I forgot to compile the code before pushing it. Could you please pull the latest version and try agian? If that still doesn't work, I'll spin up a more comprehensive test. Now it is working. Thank you.

ml1nk commented 2 years ago

We tested swap with the animation branch and it worked like before in vue2. Hopefully it gets merged this time, installing from git isn't nice.

retfah commented 2 years ago

With which version of Sortablejs should this branch work? I could not manage to make it work with the regular 1.15.0. It always deletes both involved elements. ( I'm working on another plugin to sortablejs/vue.draggable to allow "replacement" instead of "swap")

david-mohr commented 2 years ago

@retfah 1.15.0. If you let me know your config and some example code, I can hopefully try to help identify what's wrong.

retfah commented 2 years ago

@david-mohr Thank you for your support. I must confess, I gave it up on the weekend and created my own drag-drop code with swap and replace, directly based on the html-Drag-Drop-API. This was surprisingly simple. Nevertheless, I'm still using draggable in many other places in my code and will surely update to the latest version, when your pull request is implemented!

gaetandezeiraud commented 1 year ago

I have "sometime" the following error with your fork. Only when multi-drag is enabled.

sortable.esm.js:3448 

       Uncaught TypeError: Cannot read properties of undefined (reading 'isMultiDrag')
    at MultiDrag.dragOverAnimationCapture (sortable.esm.js:3448:84)
    at sortable.esm.js:850:46
    at Array.forEach (<anonymous>)
    at Function.pluginEvent (sortable.esm.js:838:13)
    at pluginEvent3 (sortable.esm.js:964:42)
    at dragOverEvent (sortable.esm.js:1867:7)
    at capture (sortable.esm.js:1887:7)
    at Sortable._onDragOver (sortable.esm.js:2112:11)
    at Sortable.handleEvent (sortable.esm.js:2348:16)

With nested draggable. Nothing more special. Can't figure out why. This prevent drag & drop. It is when I tried to move a nested component to the parent level, the error prevent the action.

Edit 1: If I set :multi-drag="false" to parent, no more problem. But I loose the multidrag support.

Edit 2: No more problem if I removed animation: 200, ghostClass: 'ghost',.

david-mohr commented 1 year ago

@Brouilles are you using the multidrag or the animation fork? Animations don't work on the plain multidrag branch

gaetandezeiraud commented 1 year ago

I use https://github.com/david-mohr/vue.draggable.next.git#multidrag

david-mohr commented 1 year ago

yeah, unfortunately animations are a bit tricky and completely untested with nested. You are welcome to try out the animation branch to see if that will help

gaetandezeiraud commented 1 year ago

Hello and thank you. Sadly, same issue with the animation branch.

image

quilkin commented 1 year ago

I'd like to use the swap plugin (is it this one? but don't know how to install it into a vue project. Can someone help?

david-mohr commented 1 year ago

@quilkin swap should work out of the box using :swap="true" on the component. nothing to install as the plugin is already available in a standard install of sortable.js

david-mohr commented 1 year ago

@Brouilles hmm, that code snippet explains why the "fixes" you mentioned address the issue, but unfortunately that's in the sortable code, not the vue part. So I'd say that disabling animations is the workaround.

quilkin commented 1 year ago

@quilkin swap should work out of the box using :swap="true" on the component. nothing to install as the plugin is already available in a standard install of sortable.js

Thanks for reply, I tried that on the 'Simple' example, but sorting still occurring. I then changed the Vue API to Composition/SFC and tried again. Found out that if I define the list as Reactive() then "swap" does not work. If the list is fixed then "swap" does work! 'app.vue' file attached. (btw, this file uses Vuetify components but I was seeing the problem before I added those)

app.zip

david-mohr commented 1 year ago

@quilkin there is a swap example. It works as expected, perhaps this might help your debugging?

quilkin commented 1 year ago

@david-mohr That sounds good, but I couldn't find one! Can you possibly point me towards it? Thanks

retfah commented 1 year ago

try both and <:swap="true"> , i.e. with/out ":"

david-mohr commented 1 year ago

https://github.com/david-mohr/vue.draggable.next/blob/multidrag/example/components/swap.vue

quilkin commented 1 year ago

https://github.com/david-mohr/vue.draggable.next/blob/multidrag/example/components/swap.vue

Hmm, not working for me, sorting still happening. ├── @vitejs/plugin-vue@4.0.0 ├── vite@4.1.4 ├── vue@3.2.47 ├── vuedraggable@4.1.0

david-mohr commented 1 year ago

strange... how are you running the test? I recommend using yarn serve from the root of the repo (after installing the depindencies), then switch to the "swap" tab.

quilkin commented 1 year ago

strange... how are you running the test? I recommend using yarn serve from the root of the repo (after installing the depindencies), then switch to the "swap" tab.

I just download the raw code into a VS Code project, which is scaffolded with Vite. Dependencies are listed in my post above (installed with npm not yarn). Sorry, but I don't understand "using yarn serve from the root of the repo "

david-mohr commented 1 year ago

if you clone my branch into a new folder and then open a terminal:

git clone  https://github.com/david-mohr/vue.draggable.next.git
cd vue.draggable.next
git switch multidrag
yarn
yarn serve

It should automatically open a new browser tab with the example project running.

quilkin commented 1 year ago

Thanks for help. I didn't have yarn installed; after I installed it I had an error 'vue-cli-service is not recognized' ; tried to install that and had a ton of errors..... I need an example that will run in VSCode.

quilkin commented 1 year ago

@quilkin swap should work out of the box using :swap="true" on the component. nothing to install as the plugin is already available in a standard install of sortable.js

Are you sure about this? On github it has // Cherrypick extra plugins import Sortable, { MultiDrag, Swap } from 'sortablejs'; Sortable.mount(new MultiDrag(), new Swap());

linuxnow commented 1 year ago

Any chance this is integrated upstream?

wayanbray commented 1 year ago

Hi everyone, Is multi-drag supposed to be compatible with clone? Because I'm facing this error when I multi-drag and clone at the same time

Cannot read properties of null (reading 'parentElement')
TypeError: Cannot read properties of null (reading 'parentElement')
    at removeNode (webpack-internal:///./node_modules/vuedraggable/dist/vuedraggable.umd.js:4376:12)
    at Proxy.onDragRemoveMulti (webpack-internal:///./node_modules/vuedraggable/dist/vuedraggable.umd.js:5226:9)
    at Proxy.onDragRemove (webpack-internal:///./node_modules/vuedraggable/dist/vuedraggable.umd.js:5197:14)
    at Proxy.eval (webpack-internal:///./node_modules/vuedraggable/dist/vuedraggable.umd.js:4805:46)
    at Sortable.eval (webpack-internal:///./node_modules/vuedraggable/dist/vuedraggable.umd.js:4816:22)
    at dispatchEvent (webpack-internal:///./node_modules/sortablejs/modular/sortable.esm.js:959:21)
    at _dispatchEvent (webpack-internal:///./node_modules/sortablejs/modular/sortable.esm.js:1006:3)
    at Sortable._onDrop (webpack-internal:///./node_modules/sortablejs/modular/sortable.esm.js:2257:13)
    at Sortable.handleEvent (webpack-internal:///./node_modules/sortablejs/modular/sortable.esm.js:2339:14)

(single-drag with clone and multi-drag without clone works perfectly fine)

david-mohr commented 1 year ago

@wayanbray I haven't done any testing with clone and multi-drag, sorry, but I would have expected it to work. I vaguely remember this error popping up in another thread. I'll see if I can find some time to check it out.

wayanbray commented 1 year ago

Thank you for your reply @david-mohr. If this can help, I made my own quick fix on onDragRemoveMulti function

// if clone
if (evt.pullMode === "clone") {
  evt.clones.forEach(element => {
    removeNode(element);
  });
  return;
} // remove items and reset transition data

Multi-elements clone data are saved in evt.clones instead of evt.clone for single elements. This works brillantly <3

Thank you very much for your work on this plugin.

david-mohr commented 1 year ago

@wayanbray awesome, thanks! I've committed the patch

oclockTwo commented 11 months ago

May I ask, has this PR not been merged into vue.draggable.next yet?

oclockTwo commented 11 months ago

I've been stuck with a question for a long time.

I'm using the swap feature of SortableJS in nuxt3, but after the swap, I update the responsive data that was used to swap, however, the data in the page is in the wrong order!

Has anyone else encountered the same problem, I'd appreciate a reply!

david-mohr commented 11 months ago

no, not merged. I'm not sure it ever will be.

I haven't used swap ever, but generally if data is not updating on the page, it's a reactivity problem. In vue, that might mean you need create and assign a new array rather than reusing existing ones.

handhikadj commented 10 months ago

@david-mohr thank you for this. However, would you update the README on https://github.com/david-mohr/vue.draggable.next/tree/multidrag? I can't see robust documentation regarding the multiDrag (and the swap) stuff

mariojankovic commented 9 months ago

@david-mohr have you heard back from @David-Desmaisons? If not, it might make sense to fork this.

david-mohr commented 9 months ago

No word from the original maintainers. I would potentially fork this, but right now I am only getting this going so I can use it in my day job. @handhikadj multiDrag works just like the upstream sortable project (as does swap). There are worked examples of each in the example directory. If you run npm serve you can launch the interactive version locally.

cthom-dev commented 5 months ago

when can we get this merged?? its been over two years 😭

duoluodexiaoxiaoyuan commented 5 months ago

Big thanks to @divinespear for the original Multidrag support in vue.draggable (SortableJS/Vue.Draggable#1052).非常感谢 vue.draggable ( SortableJS/Vue.Draggable#1052 ) 中原始的 Multidrag 支持。

I've ported it to Vue 3 (vue.draggable.next). I've also added support for the Swap plugin!我已经将它移植到 Vue 3 (vue.draggable.next)。我还添加了对 Swap 插件的支持! This branch has not been merged yet, but I need this function of yours, how should I use it?

david-mohr commented 4 months ago

@duoluodexiaoxiaoyuan You can simply reference my git repo and branch in your package.json.

"vuedraggable": "david-mohr/vue.draggable.next#multidrag"
duoluodexiaoxiaoyuan commented 4 months ago

@duoluodexiaoxiaoyuan You can simply reference my git repo and branch in your package.json.

"vuedraggable": "david-mohr/vue.draggable.next#multidrag"

i know, thank you

duoluodexiaoxiaoyuan commented 4 months ago

@duoluodexiaoxiaoyuan You can simply reference my git repo and branch in your package.json.

"vuedraggable": "david-mohr/vue.draggable.next#multidrag"

sorry, recently i find a problem image image

I want to debug souce code, how i do it.

I edit souce code in my project, it's don't effective. How i do it.