Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SortableJS / Vue.Draggable multi-drag option not working

Recently I have discovered that the SortableJS / Vue.Draggable library (https://github.com/SortableJS/Vue.Draggable) has a new option where multi-drag can be enabled to select multiple elements from an array and move them together (https://github.com/SortableJS/Vue.Draggable/pull/744).

I have seen samples where it works perfectly, for example:

  • https://jsfiddle.net/zr042g3j/3/
  • https://codepen.io/Flip535/pen/jOOKBZj
  • https://github.com/SortableJS/Vue.Draggable/pull/744

But when I have tried to use it in my project I just can find the way to make it work.

Here are the details of my project:

  • Vue: 2.6.10
  • Vuedraggable: 2.23.2

In my vue component I have imported vuedraggable this way:

import draggable from 'vuedraggable'

and I have applied this way (code has been reduced for this post purpose):

<template>
  <v-flex class="pa-3">
    <div class="instructions-wrapper py-4">
      <v-avatar size="40" color="#4C2159" class="white--text"><b>4</b></v-avatar>
      <div class="px-2">
        <h2>Revisa y asigna</h2>
        <p>Revisa la optimización del sistema y asigna o personaliza una ruta</p>
      </div>
    </div>

    <template v-for="(vehicle, key) in sortedRoutes.routes">
      <v-card class="my-4" :key="vehicle.stops.location_id">
        <v-toolbar color="primary" dark>
          <v-toolbar-title>{{ Object.keys(sortedRoutes.routes).find(key => sortedRoutes.routes[key] === vehicle) }}</v-toolbar-title>
        </v-toolbar>

        <draggable
          :key="vehicle.stops.location_id"
          :list="vehicle.stops"
          :id="key"
          group="vehicle"
          animation="150"
          :multi-drag="true"
          selected-class="multi-drag"
          ghost-class="ghost"
          :move="moveChecker"
          @start="dragStart"
          @end="dragEnd"
        >
          <div v-for="(delivery, index) in vehicle.stops" :key="delivery.id" class="draggable-element">
            <v-list v-if="delivery.location_name !== 'CEDIS'" :key="delivery.title">
              <v-list-tile>
                <v-icon>drag_indicator</v-icon>
                <v-list-tile-avatar>
                  <img :src="`https://ui-avatars.com/api/?color=fff&background=4C2159&size=128&name=${index}`">
                </v-list-tile-avatar>

                <v-list-tile-content>
                  <div>{{delivery.location_name}} {{deliveries.find(key => key.location.company_name === delivery.location_name).start_time_window ? `(${deliveries.find(key => key.location.company_name === delivery.location_name).start_time_window} - ${deliveries.find(key => key.location.company_name === delivery.location_name).end_time_window})` : ''}}
                  </div>
                </v-list-tile-content>
              </v-list-tile>
            </v-list>
          </div>
        </draggable>
      </v-card>
    </template>
  </v-flex>
</template>

I have paid attention to add the select-class attribute that is required for use the multi-drag option by SortableJS / Vue.Draggable documentation.

The object that is being printed as the draggable list is under this JSON structure:

{
  "routes": {
    "vehicle_1": {
      "stops": [
        {
          "stop_id": 0,
          "order_id": 1,
          "location_id": "DEPOT",
          "location_name": "Centro de distribución",
          "lat": -100,
          "lng": 100,
          "arrival_time": "08:00",
          "departure_time": "16:00"
        },
        {
          "stop_id": 1,
          "order_id": 2,
          "location_id": "order_2",
          "location_name": "Foo Zaas",
          "lat": -100,
          "lng": 100,
          "arrival_time": "10:00",
          "departure_time": "10:15"
        }
      ],
      "cost_matrix": [
        [
          {
            "distance_in_meters": 10,
            "travel_time_in_minutes": 10
          },
          {
            "distance_in_meters": 100,
            "travel_time_in_minutes": 100
          }
        ],
        [
          {
            "distance_in_meters": 10,
            "travel_time_in_minutes": 10
          },
          {
            "distance_in_meters": 100,
            "travel_time_in_minutes": 100
          }
        ]
      ],
      "summary": {
        "depot_name": "DEPOT",
        "demand_assigned": 234,
        "distance_in_meters": 3004,
        "travel_time_in_minutes": 157,
        "waiting_time_in_minutes": 70.1
      }
    }
  }
}

Despite all this efforts I can't make it work. I even got to replicate a slimmer version of the code basing me on one of codepens I found before and it works (https://codepen.io/Juan-Sin-Miedos/pen/jOWOyWW)

Why it isn't working on my project?

Any help would be appreciated, thank you very much!

like image 587
Juan C. Vidal Avatar asked Jun 03 '20 03:06

Juan C. Vidal


3 Answers

Because this pull request isn't merged and the latest release is very old, you need to install this version from git instead. This is what you should put into your package.json instead of the version number:

"vuedraggable": "git://github.com/divinespear/Vue.Draggable.git#multi-drag"

like image 158
Balázs Stemler Avatar answered Oct 21 '22 06:10

Balázs Stemler


"vuedraggable": "git://github.com/divinespear/Vue.Draggable.git#multi-drag"

Above repo has an issue in dist. Please use this one instead.

"vuedraggable": "git://github.com/midasdev711/Vue-DragDrop.git"
like image 37
Midas Dev Avatar answered Oct 21 '22 07:10

Midas Dev


If you want to ensure you're always using the ;latest build, you can add the MultiDrag plugin after initialisation from the SortableJS library.

Add the vuedraggable dependency to your pack.json file in the usual way:

"vuedraggable": "^2.24.3"

At the beginning of your component, instead of a basic import such as:

<script>
    import draggable from 'vuedraggable';
    
    // rest of js component code

</script>

Do the following:

<script>
    import { Sortable, MultiDrag } from 'sortablejs';
    import draggable from 'vuedraggable';

    Sortable.mount(new MultiDrag());
    
    // rest of js component code

</script>
like image 24
Kevin Lynch Avatar answered Oct 21 '22 06:10

Kevin Lynch