DEV Community

Cover image for More control over controlled forms
aryaziai
aryaziai

Posted on

5 2

More control over controlled forms

I'm currently working on a React app that's intended for a customizable news experience. The user will create a new topic and fill out the appropriate input fields. The input values are saved to state, and this data is interpolated into different fetch requests to the respective API's. Here is a rough draft of what the Create New Topic form will look like.

Each topic will serve a similar purpose to twitter hashtags. It's important that the "spacebar" and number keys are prevented in these different input fields. The first step is to see whether I can prevent these key inputs via the html input attributes. I found the following input attributes available on W3Schools:

autocomplete         height and width            formnovalidate       step 
autofocus            list                        formtarget
form                 formaction                  multiple
formenctype          formmethod                  min and max
pattern (regexp)     placeholder                 required

Although the min and max attributes will come in handy, I need to create a function that takes care of this for me. The pattern (regex) attribute could potentially help me achieve my goal, however, writing a function sounds a lot more fun. Here is a code snippet for the "#TopicName" field on my Create New Topic form:

       handleChange = (e) => {
       this.setState ({
        [e.target.name]: e.target.value
       })
      }


<Form onSubmit={(e) => {this.props.handleSubmitTopic(e, this.state) }}>
<Form.Control type='text' name="topic_title" placeholder="TopicName"

onChange={(e) => this.handleChange(e)} value={this.state.topic_title}/> /* synthetic event */

</Form>

As you can see, I'm using the "onChange" synthetic event to maintain a controlled form. My first attempt was adding a conditional statement to handleChange(e), the conditional statement would prevent typing if e.target.value === " " .

      handleChange = (e) => {
        if (e.target.value === " ") {
          console.log("space was typed")
          e.preventDefault()
        }
        else {
         this.setState ({
         [e.target.name]: e.target.value
       })
      }} 

The results were a little surprising. I was able to prevent the spacebar only if it's the first key pressed. In the gif below, you can see me successfully hitting the "if" statement, however, once I start typing letters and THEN press the spacebar, the "if" statement is no longer being accessed.

After some research, I learned that the onKeyDown synthetic event can help me achieve my goal. I created a new function called avoidSpace(e) and calling it via onKeyDown

avoidSpace = (e) => {
 if (e.key === " " {
  console.log("spacebar:", e.key)
  e.preventDefault();
 }
}

<Form onSubmit={(e) => {this.props.handleSubmitTopic(e, this.state) }}>
<Form.Control type='text' name="topic_title" placeholder="TopicName" 

onKeyPress={(e) => this.avoidSpace(e)} onChange={(e) => this.handleChange(e)} 
value={this.state.topic_title}/>  /* two synthetic events */

</Form>

I was successful in preventing the spacebar from being clicked:

Now that I know that the keyDown event works, I just need to modify the if statement to include numbers as well:

if (e.key === " " || e.key >= 0 || e.key < 10 ) {
  e.preventDefault()
}

The End

SurveyJS custom survey software

Build Your Own Forms without Manual Coding

SurveyJS UI libraries let you build a JSON-based form management system that integrates with any backend, giving you full control over your data with no user limits. Includes support for custom question types, skip logic, an integrated CSS editor, PDF export, real-time analytics, and more.

Learn more

Top comments (0)

A Workflow Copilot. Tailored to You.

Pieces.app image

Our desktop app, with its intelligent copilot, streamlines coding by generating snippets, extracting code from screenshots, and accelerating problem-solving.

Read the docs