Open Way opened 1 month ago
For anyone who is interested in a intermediate solution or kind of workaround to this request, I've figured out the following approach:
Debounce the onSwap
event to trigger the event after an amount of time but only once.
I'm using Angular, so the following code is Angular related. Anyhow, the idea will work with any other framework:
const change = new Subject<any>();
change.pipe(debounceTime(500)).subscribe((event) => {
// This event will be triggered only once every 500ms and contains the `SwapEventData`
});
const swapy = createSwapy(this.el.nativeElement);
swapy.onSwap((event) => this.change.next(event));
@Way Thank you! I think what you're looking for is disabling continuous mode:
createSwapy(container, { continuousMode: false })
Closing this issue for now — @Way let me know if this isn't working for you, and I'll be happy to take another look!
@TahaSh I tried to disable continuousMode but I do noticing the onSwap event still firing on every swap, even when I haven't released the drag yet. Is that a bug or is it intentional? It would be great to have this supported as this would allow making an API call to a database to update sort orders for example, and you only want to make a call once the drag has finalized, and not across every item it's dragging across.
Also tagging https://github.com/TahaSh/swapy/issues/53 as it's related.
I'm with @chanmathew , would be really interesting if swapy
emitted more events besides the onSwap
event. Like onDrag
or onDrop
so we can, as @chanmathew said, make some tasks at the precise moment.
Same here, I tried continuousMode: false
but it still fires events even when the item is not dropped.
Would be great to have onSwapEnd
and onSwapStart
event
For now I added a debounce so that it only fires after an amount of inactive time
import { SwapArray } from "@/lib/types"
import { useLayoutEffect, useRef } from "react"
import { createSwapy } from "swapy"
import { useDebouncedCallback } from "use-debounce"
interface Props {
onSwap?: (data: SwapArray) => void
debounce?: number
}
/**
*
* @param onSwap
* @returns containerRef
*/
const useDraggable = ({ onSwap, debounce = 2000 }: Props) => {
const containerRef = useRef<HTMLDivElement>(null)
const swapy = useRef<ReturnType<typeof createSwapy>>()
const debounced = useDebouncedCallback(
(data: SwapArray) => onSwap?.(data),
debounce
)
useLayoutEffect(() => {
if (containerRef.current && !swapy.current) {
const _swapy = createSwapy(containerRef.current, {
animation: "dynamic",
})
swapy.current = _swapy
swapy.current.onSwap((event) => {
debounced(event.data.array)
})
}
}, [containerRef, debounced])
return containerRef
}
export default useDraggable
@chanmathew Disabling continuousMode
doesn't swap on drop; instead, it waits about 100ms after you stop before swapping. I'll be adding a new mode soon that will allow swapping right on drop.
First of all thank you for your great tiny and helpful library!
My request proposes adding an
onSwapEnd
event. This event would trigger when a drag-and-swap action is completed, allowing developers to detect the end of the drag operation and perform additional actions or updates as needed. This feature would enhance the flexibility and interactivity of the drag-to-swap experience.For instance, when reordering items, I don't need an event triggered for each individual swap. Instead, I require a single event that fires once the user has finished dragging and the final order is set.