Closed Kocal closed 6 years ago
Well... When I was writing my issue, I thought about a dirty solution, but it's working as expected..
I need to specify a ref to <draggable>
, and now I can access private Sortable
instance and make my things like that:
<template>
<div>
<draggable
ref="draggable"
v-model="items"
:options="options"
@start="onDraggableStart"
@update="onDraggableUpdate"
>
<div v-for="item in items">{{ item.name }}</div>
</draggable>
</div>
</template>
<script>
export default {
data() {
return {
options: {
disabled: false,
}
}
},
methods: {
onDraggableStart() {
this.currentOrder = this.$refs.draggable._sortable.toArray();
},
onDraggableUpdate() {
this.options.disabled = true;
axios
.post(...)
.then(() => ())
.catch((error) => {
// Revert order
this.$refs.draggable._sortable.sort(this.draggableCurrentOrder);
})
.finally(() => this.options.disabled = false);
},
}
}
</script>
I think you can close this issue, and put label « question » I guess.
I was looking for a built in solution for reverting the order just like you. If I assume that your draggable list is defined in your Vue instance's data (don't see your list defined in code), then the below is a simple solution to revert:
onDraggableUpdate(event) {
...
.catch(error => {
let moved = this.list.splice(event.newIndex, 1);
this.list.splice(event.oldIndex, 0, moved);
})
.finally( ...);
...
}
Hello, this is much more a question for stackoverflow than an issue for this repo. Vue.draggable kepts drag-and-drop operation in sync with an array synchroneously. That is its scope. If you have to propagate this changes asynchroneously with an ajax call, and potencially revert them as the operation failed this is a different topic with no built-in solution provided. That said vue.draggable provides tools that can be used to build such a behavior. For example you may: -have two arrays original having the same elements (data from server) -use on array in a vue.draggable component -listen to the change of this array and perform ajax call when they happens -in case of success => copy the session array into the server array -in case of failure => copy the server array into the session array -use disabled option to avoid dnd during ajax call
It all depends on how u want to build user interaction and how your data and API are build.s Check also issue #390
I was looking for a built in solution for reverting the order just like you. If I assume that your draggable list is defined in your Vue instance's data (don't see your list defined in code), then the below is a simple solution to revert:
onDraggableUpdate(event) { ... .catch(error => { let moved = this.list.splice(event.newIndex, 1); this.list.splice(event.oldIndex, 0, moved); }) .finally( ...); ... }
Hi @davidvleung
Thanks, the solution you provided was just what I was looking for. However, to make it work I needed to reference the first element in the variable 'moved' because it is an array from the splice method.
So I changed this line
this.list.splice(event.oldIndex, 0, moved);
to this
this.list.splice(event.oldIndex, 0, moved[0]);
2020 update: In addition to @rolandjlevy's modifications, I also needed to modify the "event.newIndex" part to "event.moved.newIndex" (and the same for the oldIndex). So the code became:
onDraggableUpdate(event) {
...
.catch(error => {
let moved = this.list.splice(event.moved.newIndex, 1);
this.list.splice(event.moved.oldIndex, 0, moved[0]);
})
.finally( ...);
...
}
For anyone landing on this issue:
Much easier solution is to store the initial order of all cards in all columns on card movement start
and if something fails to restore the order.
<div v-for="(column, columnIndex) in columns" :key="columnIndex">
<h2>{{ column.name }}</h2>
<draggable
:list="column.cards"
group="cards"
@start="saveInitialOrder"
@change="move"
>
<template #item="{ element }">
<div >{{ element.name }}</div>
</template>
</draggable>
</div>
// data:
columns: [
{ name: 'Column 1', cards: [{ id: 1, name: 'Card 1.1' }, { id: 2, name: 'Card 1.2' }] },
{ name: 'Column 2', cards: [{ id: 3, name: 'Card 2.1' }, { id: 4, name: 'Card 2.2' }] },
{ name: 'Column 3', cards: [{ id: 5, name: 'Card 3.1' }, { id: 6, name: 'Card 3.2' }] }
],
initialColumns: []
// methods
saveInitialOrder() {
// Save the initial order of columns and cards
this.initialColumns = JSON.parse(JSON.stringify(this.columns));
},
move() {
// storing
if (..storing failed..) {
this.restoreInitialOrder();
}
},
restoreInitialOrder() {
// Restore the initial order of columns and cards
this.columns = JSON.parse(JSON.stringify(this.initialColumns));
}
Hey, I would like to know how is it possible to cancel a drop and so revert to original positions, if my AJAX request fails.
I know that I can hook
onMoveCallback
and returnfalse
to revert to original positions, but AJAX request works asynchronously, not synchronously...So I found an example with
Sortable
only (https://github.com/RubaXa/Sortable/issues/266) which useonUpdate
event, but I don't know how to reproduce it withVue.Draggable
.Here is my code:
Maybe I'm missing something... Thanks!