Movatterモバイル変換


[0]ホーム

URL:


Skip to content
DEV Community
Log in Create account

DEV Community

Cover image for How to change numeric input by dragging in React?
Graftini profile imageSharad Chand
Sharad Chand forGraftini

Posted on • Originally published atblog.graftini.com

     

How to change numeric input by dragging in React?

The above GIF is one of the interactions that I love aboutFigma . To change the position of an item, I do not have to use a keyboard at all. Just a mouse is enough.

So in this article we are going to create a numeric input field whose value can be changed by dragging on its labelfrom scratch. We needed this forGraftini because we think a visual toolshould not require keyboard for most interactions.

If you are eager to see the code and try it out for yourself, then jump to CodeSandbox athttps://codesandbox.io/s/drag-number-input-z2rnj.

Let us first create a simple input

We can start by creating an input which reads from and writes the values to a state. If you have already created forms this should be simple enough to understand.

functionInput(){const[value,setValue]=useState(0);constonInputChange=useCallback((ev)=>setValue(parseInt(ev.target.value,10)),[]);return(<inputvalue={value}onChange={onInputChange}style={{padding:8,}}/>);}
Enter fullscreen modeExit fullscreen mode

We are creating a state which stores the current value of the input. This state will be updated when the input changes via the keyboard.

Now we need a label that fits right in with the input

We need the label to be an anchor on which the mouse interactions can be added. The input itself cannot be the anchor because then it will ruin how input fields normally are expected to behave. The code that captures that idea can look like:

<divstyle={{display:"flex",border:"1px solid #CCC",alignItems:"center",borderRadius:4,fontFamily:"sans-serif",width:300,}}><spanstyle={{padding:8,color:"gray",cursor:"ew-resize",userSelect:"none",}}>Count</span><inputvalue={value}onChange={onInputChange}style={{flex:1,padding:8,border:"none",outline:"none",}}/></div>
Enter fullscreen modeExit fullscreen mode

The above code is just visual cosmetics. You can make it to look however you see fit. Now the input should look something like:
image.png

Adding mouse interactions on the label

We will extract the label into its own component to make it easier to write & understand the code. Then we will add three mouse interactions in it. One on the label itself and two on the document. Why? We will discuss it along side the code.

functionDragLabel({value,setValue}){// We are creating a snapshot of the values when the drag starts// because the [value] will itself change & we need the original// [value] to calculate during a drag.const[snapshot,setSnapshot]=useState(value);// This captures the starting position of the drag and is used to// calculate the diff in positions of the cursor.const[startVal,setStartVal]=useState(0);// Start the drag to change operation when the mouse button is down.constonStart=useCallback((event)=>{setStartVal(event.clientX);setSnapshot(value);},[value]);// We use document events to update and end the drag operation// because the mouse may not be present over the label during// the operation..useEffect(()=>{// Only change the value if the drag was actually started.constonUpdate=(event)=>{if(startVal){setValue(event.clientX-snapshot);}};// Stop the drag operation now.constonEnd=()=>{setStartVal(0);};document.addEventListener("mousemove",onUpdate);document.addEventListener("mouseup",onEnd);return()=>{document.removeEventListener("mousemove",onUpdate);document.removeEventListener("mouseup",onEnd);};},[startVal,setValue,snapshot]);return(<spanonMouseDown={onStart}style={{padding:8,color:"gray",cursor:"ew-resize",userSelect:"none",}}>Count</span>);}
Enter fullscreen modeExit fullscreen mode

Now try running it up and voila 🎉🎊 you have your own drag to change numeric input.

2021-06-29 16.27.09.gif

It looks awesome doesn't it? Though the cursor during the operation does not look good. This could be something that you can fix. 😋

The full code is at CodeSandbox for you to try it outhttps://codesandbox.io/s/drag-number-input-z2rnj?file=/src/App.js.

Fork it & make improvements to it. Till then ✌️.

Top comments(3)

Subscribe
pic
Create template

Templates let you quickly answer FAQs or store snippets for re-use.

Dismiss
CollapseExpand
 
tombalev profile image
Tom Balev
  • Education
    University of Hertfordshire
  • Work
    CEO INTEGNITY
  • Joined
• Edited on• Edited

Change:

if (startVal) {     setValue(event.clientX - snapshot);}
Enter fullscreen modeExit fullscreen mode

to:

if (startVal) {     setValue(snapshot + event.clientX - startVal);}
Enter fullscreen modeExit fullscreen mode

to prevent zeroing out the input on next drag

CollapseExpand
 
dakotys profile image
Jaroslav Rojík
  • Joined
• Edited on• Edited

You forgot to remove mousemove listener on mouse release:
const onMouseUp = () => {
document.removeEventListener("mousemove", onMouseMove);
document.removeEventListener("mouseup", onMouseUp);
setStartPos(0);
};

CollapseExpand
 
dariansampare profile image
Darian Sampare
Is it broken yet or do you want me to try fixing it again?
  • Location
    Victoria BC
  • Work
    Intermediate Full Stack Engineer at Certn
  • Joined

Very nice start but you'll have to do some math if you want a default value other than 0!

Are you sure you want to hide this comment? It will become hidden in your post, but will still be visible via the comment'spermalink.

For further actions, you may consider blocking this person and/orreporting abuse

Graftini is a nocode designer that deploys your designs to full-fledged web apps.

More fromGraftini

DEV Community

We're a place where coders share, stay up-to-date and grow their careers.

Log in Create account

[8]ページ先頭

©2009-2025 Movatter.jp