vue-dragula icon indicating copy to clipboard operation
vue-dragula copied to clipboard

Cannot reorder within the same bag in Vue 2.0

Open amcsi opened this issue 9 years ago • 13 comments

Based on https://github.com/Astray-git/vue-dragula/issues/19#issuecomment-254199811, indeed you cannot seem to reorder properly within the same bag.

I'm not yet sure if this is a Vue 2.0 issue or a vue-dragula issue. I'm trying to investigate, but I'm not that familiar with either projects. I'm also having trouble creating a small example, so please help me out @Astray-git if you can

amcsi avatar Oct 22 '16 16:10 amcsi

Alright so this is happening because of Vue 2.0. This is not a bug, but expected behavior.

The key is with the comment here: http://archive.forum.vuejs.org/post/10869

Basically in order to get vue-dragula to work in Vue 2.0, you need to make sure that you pass to v-dragula the original prop for what you want to move around, but when iterating you need to work with a data() copy.

Here is an example of what I needed to do to get it to work in my project: https://github.com/amcsi/skill-builder/commit/a221dd6f07496374c137b1102881938f7fbc4294

Tagging @deiucanta because you are the one that brought this issue to our attention.

amcsi avatar Oct 22 '16 17:10 amcsi

I need to re-open this, because it appears that I'm wrong.

Unfortunately doing the separation between prop and local changes aren't enough, because although it will work for dragging around, if anything else is changed in the parent, then all the moving around stuff will be overridden

If you look here https://github.com/vuejs/vue/issues/2873 you'll find:

Props Behavior

.once and .sync are deprecated. Props are now always one-way down. To produce side effects in the parent scope, a component needs to explicitly emit an event instead of relying on implicit binding.

Mutating a prop locally is now considered an anti-pattern, e.g. declaring a prop a and then set this.a = someOtherValue in the component. Due to the new rendering mechanism, whenever the parent component re-renders, the child component's local changes will be overwritten. In general, in 2.0 you should treat props as immutable. Most use cases of mutating a prop can be replaced by either a data property or a computed property.

So unfortunately there is no way to have changes go upwards without using events or having something passed down that can be used. Maybe this project is going to need some sort of new helper method that creates like some sort event-listener wrapped version of the elements so that when you pass that wrapped something to v-dragula and its splice() and such methods are called, then it would capture that and instead do some sort of event-based manipulation of the ancestor to change the data there. I don't know if that made sense.

So this issue is going to need to stay until further notice, and until then this plugin is unfortunately not usable in Vue 2.0

amcsi avatar Oct 24 '16 10:10 amcsi

I don't know how I missed this one... so it's not compatible with 2.0 yet? :(

vitobotta avatar Nov 05 '16 18:11 vitobotta

@vitobotta I made it compatible with Vue 2 now dev (still a WIP) and demo

I still can't quite grasp the concept of bags however. I wish @amcsi or someone else "in the know" could explain the relationships between the VM model, containers, bags service etc. What are the constraints. When must things be called and configured in the Vue/component life cycle for Vue2? Thanks :)

kristianmandrup avatar Nov 12 '16 15:11 kristianmandrup

Unfortunately I don't quite know. It is like a group where items within a bag can only be moved to places where there's a bag with the same value. Kind of like a radio input's name attribute connects radio elements together. But it's best if you asked @Astray-git, because I hardly know anything about the project :(

amcsi avatar Nov 12 '16 16:11 amcsi

A solution for vue2 DOM order, we must provide a key for v-for directive to update DOM order.

v-for="item in list" add :key="item.id" for object items, :key="item" for plain string. see: https://vuejs.org/v2/guide/list.html#key

Astray-git avatar Nov 14 '16 06:11 Astray-git

@Astray-git as far as I know, key is for optimizing re-rendering by not having to re-render bits where they their subdom is already in the correct place and in the correct state. And that using a key wouldn't solve the issue of the Vue2 caveat that you cannot mutate props coming from a parent, and that you have to use the event bus or vuex

amcsi avatar Nov 14 '16 11:11 amcsi

that you have to use the event bus or vuex

How would you handle data mutation with vuex? By manually hooking into the dragula events and finding the moved element and the from and to models, am I right? Or there's some shortcut I'm missing here?

andreiglingeanu avatar Dec 05 '16 19:12 andreiglingeanu

Any news on this issue? I was just trying vue-dragula for the first time in a small vue 2.2.4 project, but can't manage to get re-ordering items in a list working. I added :key but that seems not to make any difference.

josdejong avatar Apr 29 '17 11:04 josdejong

You can try using vue2-dragula which has a fully customizable data model and supports a single bag model.

kristianmandrup avatar Apr 29 '17 12:04 kristianmandrup

Ahhh, thanks Kristian! vue2-dragula works like a charm (:key must be defined though).

josdejong avatar Apr 29 '17 12:04 josdejong

@josdejong Great to hear! You are very welcome to add your use case as an example in the new Wiki docs I've just added: Usage-examples

kristianmandrup avatar Apr 29 '17 12:04 kristianmandrup

I'm sorry I'm lacking time to work out an example for the examples section. I use dragula just to do reordering of rows in a table, it's a simple use case.

josdejong avatar Apr 29 '17 12:04 josdejong