skip to Main Content

I want to block "-" (dash) from entering into the input field by the user. The "-" code is 189.

Here’s my code :

import React, { useEffect, useState } from "react"

interface Props {
  value: string
}

function InputFormat(props: Props) {
  const [stateValue, setStateValue] = useState(() => value)

  const handleChange = (event: any) => {
    setStateValue(event.target.value)
  }

  const handlekeyDown = (event: any) => {
    if (event.keycode === 189) {
      return
    }
  }

  return (
    <>
      <input
        onKeyDown={(e) => handlekeyDown(e)}
        value={stateValue}
        onChange={(e) => handleChange(e)}
      />
    </>
  )
}

export default InputFormat

This is not working as expected. I am trying to return if the keycode is 189 form dash, but still I’m able to type. How can I achieve this here (notice this is a controlled component).

5

Answers


  1. First of all, KeyboardEvents do not have a keycode. They have a deprecated keyCode (will be removed at some point).

    Possible replacements for your check:

    • event.key === '-'
    • ['Minus', 'NumpadSubtract'].includes(event.code)

    Secondly, to prevent the change in <input />‘s value, you have to call preventDefault() method on event:

    const handleKeyDown = (event: KeyboardEvent) =>
      event.key === "-" && event.preventDefault()
    

    Side note: preventing default on user input is considered detrimental UX. The user does not feel respected. Disabling keyboard user input in <input/>s has been demonstrated to increase bounce rate and decrease user loyalty of web-pages.

    A more respectful way of telling them they’re not allowed particular values in <input /> is to display an invalidity message about the current value, coupled with some visual indicator (red border, etc…). Or, as @DanielBeck pointed out in the comments, to simply disregard the dash where you’re consuming it (without overriding the user input’s value).

    Login or Signup to reply.
  2. Check event.key (keyCode is deprecated) and use event.preventDefault() to stop the character from being entered.

    const handlekeyDown = (event) => {
      if (event.key === '-') {
        event.preventDefault();
      }
    }
    
    Login or Signup to reply.
  3. Well, you could return if the value is - in your handleChange function.

    const handleChange = (event: any) => {
        if(event.target.value == '-') {
          return;
        }
        setStateValue(event.target.value)
      }
    
    Login or Signup to reply.
  4. Listening keyDown and use preventDefault it is not the best way.

    A more attractive solution is move condition to onChange:

    import React, { useEffect, useState } from "react"
    
    interface Props {
      value: string
    }
    
    function InputFormat(props: Props) {
      const [stateValue, setStateValue] = useState(() => value)
      const onChangeHandler = (e) => {
        if (e.target.value.includes('-')) return
        setValue(e.target.value)
      }
    
      return (
        <>
          <input
            value={stateValue}
            onChange={onChangeHandler}
          />
        </>
      )
    }
    
    export default InputFormat
    

    The best solution it will be if you modify this code with regex. It would be much more scalable.

    const noDashesRegex = /[-]+/
    
    if (noDashesRegex.test(e.target.value)) return
    
    Login or Signup to reply.
  5. Ideally you’d either use a regular expression or just includes(), but
    if you insist on using a keycode, you just convert the character to a keycode, and if any of the characters within your input string match your key code, then return, else, update your state:

    Code sandbox example, but I’m testing for "e" instead of the dash:
    https://codesandbox.io/s/upbeat-forest-7qxlub?file=/src/App.js

    import "./styles.css";
    import { useState } from "react";
    
    export default function App() {
      const [field, setField] = useState("");
    
      const sanitizeInput = (e) => {
        for (let i = 0; i < e.target.value.length; i++) {
          let code = e.target.value.charCodeAt(i) - 32;
          if (code === 69) {
            return;
          }
        }
        setField(e.target.value);
      };
    
      return (
        <div className="App">
          <h1>Hello CodeSandbox</h1>
          <h2>Start editing to see some magic happen!</h2>
          <input value={field} onChange={(e) => sanitizeInput(e)} />
        </div>
      );
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search