javascriptvue.jsvuedraggable

Vue Draggable - How to only replace item chosen to prevent shifting all other items on grid?


Here's an example to test: https://codesandbox.io/s/j4vn761455?file=/src/App.vue:112-116

Step 1: Drag 4 to 5. As you see, 4 and 5 switch places

Step 2: Drag 1 to 6, as you see, 1 goes where 6 was, 6 gets pushed to the side, and 2, 3, 4, and 5 all shift over.

I would like though is to keep existing items untouched, moving 1 and 6 should move 1 to 6 and 6 to 1 space on the grid. All other items should remain in their spaces.

I have tried using sort=false this had no effect, and without a group=, it disables all dragging.

Is this possible?

I'd like the items in the grid to be stationary and only moved based on desired selection. If I'm not using the right tool, is there something else that could accomplish this? Think about if the grid was icons, it does make a good UI when moving icons to a selection and then all the previous icons automatically shift over. Would be very annoying to the user.

Hope this makes sense, if you need more details, comment below and I'll revise/update as needed.


Solution

  • While vuedraggable does not provide swapping by default https://github.com/SortableJS/Vue.Draggable/issues/466 , there's a great article that explains how to implement it yourself.

    This is your modified code sandbox https://codesandbox.io/s/vuedraggable-with-css-grid-forked-wk4xk

    Basically, you need to implement the swapping behaviour yourself by storing the current and future indexes (note, I changed the name of your list to "items" just to make it easier to port the code in the article).

    <draggable v-model="items" :move="handleMove" @end="handleDragEnd">
    

    In your script

    methods: {
        handleDragEnd() {
          this.futureItem = this.items[this.futureIndex];
          this.movingItem = this.items[this.movingIndex];
          const _items = Object.assign([], this.items);
          _items[this.futureIndex] = this.movingItem;
          _items[this.movingIndex] = this.futureItem;
    
          this.items = _items;
        },
        handleMove(e) {
          const { index, futureIndex } = e.draggedContext;
          this.movingIndex = index;
          this.futureIndex = futureIndex;
          return false; // disable sort
        }
      }