Open mixtur opened 6 years ago
Yes, this please!
Basically I cannot place any <input>
element within the Draggable because when focusing it, it automatically looses the focus and it's impossible to write into it...
Since every click fires the onStart
and onStop
callbacks we can set a flag onDrag
so we know we're dragging and check it onStop
, like so:
// class property
this.isDragging = false;
<Draggable
onDrag={() => this.isDragging = true}
onStop={() => {
if (!isDragging) {
// onClick stuff here
}
this.isDragging = false;
}
/>
I think you'll never enter section inside your if
then.
Ow. Sorry, you are right of course. But the point is to not do it manually and hide this logic inside react-draggable. Also this is a special case of minimum mouse offset. Namely zero offset. But if element weren't draggable it would trigger click even if there were any offset. For regular onClick to occur it is enough to have 'mousedown' and 'mouseup' on thee same element. So with draggable there is ambiguity on what user means if he or she does mousedown-mouseup on the same element even if there is some mousemove in between. Users aren't perfect, they can twitch a little when clicking.
@ibc you can call stopPropagation for mousedown on your input.
@ibc you can call stopPropagation for mousedown on your input.
Yes, but I don't want to (or just can't) pollute 3rd party components that I want to put over the draggable container.
Another use case (where @bmpinto solution doesn't work):
We have multiple elements within a div. Some of these elements are draggable and some are clickable. Upon onStart
we check if an item is draggable and if not we return false
.
Problem is that if an element is clickable, it is not draggable, which means we get neither onDrag
nor onStop
.
As with #419, a drag also produces a superfluous click at the end.
Edit: For my use case, turns out mouseDown
is the way to go when wanting to select something.
Yeah this confused me as well, basically onStart
prevents any click event from continuing the event capture phase, while onDrag
does not. Therefore changing to former to the latter fixed the issue for me.
I have a similar use-case which I've done the workarounds for, but it still provides a suboptimal user experience.
My use-case is trying to replicate the headers in the VS Code sidebar -- you can click to expand/collapse them, but you can also drag them to re-order.
You'll notice that in vscode you need to drag about 3 pixels before the clone of the element appears at your mouse location -- this works well because clicks are treated as clicks, and drags as drags.
Even with the workaround above, I find that unless I'm super-precise when clicking, and don't move the mouse even 1 pixel, I get the drag animation when what I was really doing was a "slightly sloppy" click.
I'd like the Draggable to not start firing onStart or onDrag until the mouse has moved at least minimum
pixels. Is there another workaround that I'm not considering?
Hey, I'm facing a similar problem with OnClick & OnDrag.
Currently, I have to click, and then the draggable piece will follow my mouse. I think it'd be a bit more intuitive if all I had to do was hold down click and drag, then release to drop the draggable piece to the dragged location. (Demo : the road pieces in https://detour-bus-site.web.app/)
How can I fix this? Drag seems to work fine on mobile devices, but creates this issue on desktop for me.
Make your component controlled using position then you can detect click and drag by change in coordinates.
Make your component controlled using position then you can detect click and drag by change in coordinates.
I am using position to control the component. However, I am unable to click and drag. Instead, I have to click and the object then follows my mouse.
@yjaju actually your ondrag function will get the current position on movement , you can then supply that to a component based on need . https://github.com/adityasreeram007/freeform-editor check my repo
Thanks so much for sharing your repo!
I have an update regarding the problem : Draggable is working perfectly with div elements, but not img elements. Draggable works with the first code snippet, not with the second. No parameters have been changed.
<Draggable ...parameters>
<div style={{backgroundColor: 'yellow', width: '20px', height: '20px'}}/>
</Draggable>
<Draggable ...parameters>
<img src={key.img}
</Draggable>
How do I fix this for img?
@yjaju check if both the elements are absolute positioned . Try to pass the parameters as individual props than populating entirely.
@adityasreeram007 both the elements are absolute positioned (they share the same css class as well).
I used background-image in div to get it working, but just curious as to why it isn't working with image tags. Here's my entire code for both variants (first one works, second one doesn't):
<Draggable key={key.img} position={{x:key.x, y:key.y}} onDrag={(e, data)=>dragRoad(e, data, index)} onStop={(e, data)=>stopDragRoad(e, data, "single")}>
<div className="road_img" style={{backgroundImage: `url(${key.img})`, backgroundRepeat: "no-repeat"}}/>
</Draggable>
<Draggable key={key.img} position={{x:key.x, y:key.y}} onDrag={(e, data)=>dragRoad(e, data, index)} onStop={(e, data)=>stopDragRoad(e, data, "single")}>
<img src={key.img} className="road_img" alt="Draggable Road Piece"/>
</Draggable>
Key of two different elements in Dom should not be same. Give different key value.
The keys are different! :)
I have created an array map as follows:
{road_array.map((key, index) =>
<Draggable key={key.img} position={{x:key.x, y:key.y}} onDrag={(e, data)=>dragRoad(e, data, index)} onStop={(e, data)=>stopDragRoad(e, data, "single")}>
<div className="road_img" style={{backgroundImage: `url(${key.img})`, backgroundRepeat: "no-repeat"}}/>
</Draggable>)
}
this should be perfect. I ve used the same way to render elements it works. if this doesnt work you should shift to HOC.
@adityasreeram007 thanks so much, I'll shift to HOC!
@yjaju
I have the same problem- I click and then the Draggble item follows my mouse and doesn't stop, even if I click again.
This happens when I pass a function to onStop
prop, if I don't specify onStop
it works fine.
Did you solve this?
@noaLeibman i fixed it by using a div block inside Draggable (for some reason, Draggable fails with images. So I added a background-image to the div and used that instead)
Could you share your Draggable code? i can take a look and try to help!
@yjaju
Hey!
I used onStop
incorrectly and returned false in my implementation.. so that was my problem.
But thank you anyway!:)
Now every click triggers both
onStart
andonEnd
. It would be nice if I could specify maximum mouse offset and/or timeout until which drag operation will not start.