Related to https://github.com/SortableJS/Vue.Draggable/issues/45#issuecomment-313503906
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 return false 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 use onUpdate event, but I don't know how to reproduce it with Vue.Draggable.
Here is my code:
<template>
<div>
<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() {
// will not work because I don't have access to Sortable instance
this.currentOrder = this.toArray();
},
onDraggableUpdate() {
this.options.disabled = true;
axios
.post(...)
.then(() => ())
.catch((error) => {
// Revert order
this.sort(this.currentOrder); // will not work too
})
.finally(() => this.options.disabled = false);
},
}
}
</script>
Maybe I'm missing something...
Thanks!
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:
```javascript
onDraggableUpdate(event) {
...
.catch(error => {
let moved = this.list.splice(event.moved.newIndex, 1);
this.list.splice(event.moved.oldIndex, 0, moved[0]);
})
.finally( ...);
...
}
Most helpful comment
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 privateSortableinstance and make my things like that:I think you can close this issue, and put label 芦聽question 禄聽I guess.