Open philippkuehn opened 6 years ago
Hey @philippkuehn, thanks for your suggestion. We definitely have plans to add a group
option for Sortable
, but it would work slightly different. Due to design choices we made, it's not possible to drag between draggable
instances (includes Sortable and all other modules), instead we expose an API to allow adding of additional containers, e.g. sortable.addContainer()
/sortable.removeContainer()
. This way you can dynamically add more containers as your application may render more content.
Here an example of how you could get that behaviour working today:
const sortable = new Sortable(document.querySelectorAll('.selector-for-all-lists'))
sortable.on('sortable:sort', (sortableEvent) => {
const {source, over} = sortableEvent;
// You'll need to add `data-group` attributes to your elements instead
if (source.getAttribute('data-group') !== over.getAttribute('data-group')) {
// Canceling the `sortable:sort` event will prevent sorting
sortableEvent.cancel();
}
})
Thanks for the clarification! Unfortunately, this makes it impossible to build portable and encapsulated web components, isn't it? 😟
I hope it's not out of context but this is what a simple Vue.js <sortable />
component looks like.
<template>
<div ref="container">
<slot />
</div>
</template>
<script>
import { Sortable } from '@shopify/draggable'
export default {
name: 'sortable',
data() {
return {
sortable: null,
}
},
mounted() {
this.sortable = new Sortable(this.$refs.container, {
draggable: '.draggable'
})
},
beforeDestroy() {
this.sortable.destroy()
}
}
</script>
This component can be used like this.
<sortable>
<div class="draggable">Item 1</div>
<div class="draggable">Item 2</div>
</sortable>
<sortable>
<div class="draggable">Item 3</div>
<div class="draggable">Item 4</div>
</sortable>
But at the moment there is no way that these two lists can communicate with each other.
The only solution I have in mind is to store this sortable instance
const sortable = new Sortable(document.querySelectorAll('.selector-for-all-lists'))
somewhere globally and each <sortable />
component will add and remove its container on mounted/beforeDestroy to this instance. But again – this is not encapsulated.
This also becomes much more complicated if there are multiple groups, because then you have to save one instance globally for each group.
I concur with @philippkuehn
A solution that may, according to what your @tsov say, change the current API would be to simply have a “group” property for lists that would specify families of interchangeable elements. Taking inspiration from the nice design in https://github.com/RubaXa/Sortable we may allow a “group” option upon the creation of any Draggable instance:
Hey all, first apologies if writing this on a wrong place.
I'm having similar problem with connecting two separate components to handle sorting between separate. Like @philippkuehn said and @tsov confirmed, only way is to have a single instance of Sortable.
Aside from sort between groups I need additional option to drop sortable elements on dropzones and that means Sortable
is not going to work, but Draggable
and then handling all events manually.
I was surprised that Draggable has all events needed to make this work and they are easy to use, so that is great!
Then it is basically copying Sortable.js
in my vue component Sortable.vue
and each component attaching event listeners to that global draggable and handling events individually.
The problem I'm having right now is how to reference component instance and dom element in a nice way. Ugly solution is by attaching source component instance to a source draggable element like this:
onDragStart(event) {
if (this.isChild(event)) {
event.source._source = {
component: this,
startIndex: this.index(event.source)
}
}
}
Anyone trying to implement shopify draggable with Vue I would appreciate any help with this. Again, this is working but it is ugly, and I'm not sure will it cause any memory leaks. Thanks
https://github.com/dam1r89/vue-shopify-draggable-components/tree/master/src/components
Is there a way to drag items between two sortable instances without initializing both at the same time?
I know there is a demo for multiple containers.
But if you think in components (react, vue, …) this is likely a problem because for each
sortable
component there is onesortable
instance. It would be nice if these instances could work together. Many other drag and drop plugins provide a way to set agroup
property for doing this. This could look something like this:Maybe something like this is already possible now?