5

I want to restrict users from entering negative values. I am using min = "0". With this i can restrict users from decrementing to 0, i.e, users can only decrement value till 0. But they are able to type "-". How to prevent in react js.

https://codesandbox.io/s/react-input-example-forked-xnvxm?file=/src/index.js

<input
   type="number"
   min="0"
   step="1"                        
   onChange={this.handleChange}                        
   className="w-100"
   value= "1"
   />
codemonkey
  • 7,325
  • 5
  • 22
  • 36
theWanderer
  • 576
  • 2
  • 10
  • 30

8 Answers8

10

You can add an onKeyPress listener to the input element and that will be triggered before the onChange and call a function that will prevent default behaviour when the minus button is pressed.

const preventMinus = (e) => {
    if (e.code === 'Minus') {
        e.preventDefault();
    }
};

<input               
  type="number"
  min="0"
  onKeyPress={preventMinus}
/>

Note that this will still allow negative values to be pasted into the input. For this, you can add an onPaste listener and check the clipboard data to see if it's negative and prevent the default behaviour.

const preventPasteNegative = (e) => {
    const clipboardData = e.clipboardData || window.clipboardData;
    const pastedData = parseFloat(clipboardData.getData('text'));

    if (pastedData < 0) {
        e.preventDefault();
    }
};

<input               
  type="number"
  min="0"
  onPaste={preventPasteNegative}
  onKeyPress={preventMinus}
/>
David Vega
  • 579
  • 3
  • 13
ThanishSid
  • 109
  • 2
  • 3
3

Handling Empty Input & Negative Numbers

// Converting App into Class-Component
class App extends React.Component {
  // Set State
  constructor(props) {
    super(props);
    this.state = {
      number: ""
    };
  }

  render() {
    return (
      <div className="App">
        <input
          type="number"
          min="0"
          step="1"
          onChange={(e) => {
            let val = parseInt(e.target.value, 10);
            if (isNaN(val)) {
              this.setState({ number: "" });
            } else {
              // is A Number
              val = val >= 0 ? val : 0;
              this.setState({ number: val });
            }
          }}
          className="w-100"
          // Assign State
          value={this.state.number}
        />
      </div>
    );
  }
}
1

You can use a regex to validate the input before setting the state of your input and sync the input value with your state value.


<input
  type="number"                  
  onChange={this.handleChange}                        
  className="w-100"
  value= {this.state.inputVal}
/>

validateNumber = (value) => {
  //true for digits only.
  const regex = /^[0-9]+$/
  return regex.test(value);
}
handleChange = ({target}) => {
  const {name,value} = target;
  const {inputVal} = this.state;

  if(value === '') {
    return this.setState({inputVal:''});
  }

  if(this.validateNumber(value)) {
    this.setState({inputVal:value})
  } else {
    this.setState({inputVal:inputVal})
  }
}

Asit Prakash
  • 341
  • 3
  • 9
1

Use some local component state to hold the input's value and use Math.max(0, value) to ensure the value prop/attribute is a non-negative value. The input's value will be a string in the onChange handler so remember to coerce it back to a number value for state.

function App() {
  const [value, setValue] = React.useState(0);
  return (
    <div className="App">
      <label>
        Try entering a negative value
        <input
          type="number"
          min="0"
          step="1"
          className="w-100"
          value={value && Math.max(0, value)}
          onChange={e => setValue(e.target.value ? Number(e.target.value) : e.target.value)}
        />
      </label>
    </div>
  );
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.13.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.13.1/umd/react-dom.production.min.js"></script>
<div id="root"></div>
Drew Reese
  • 165,259
  • 14
  • 153
  • 181
0

You can filter out input value inside handlechange. Something like this:

const App = () => {
  const [value, setValue] = useState("");

  const handleChange = (e) => {
    if (!isNaN(e.target.value)) {
      setValue(e.target.value);
    }
  };
  return (
    <div className="App">
      <input
        type="text"
        value={value}
        onChange={handleChange}
        className="w-100"
      />
    </div>
  );
};

Here is the demo: https://codesandbox.io/s/react-input-example-forked-kr2xc?file=/src/index.js

Shubham Verma
  • 4,918
  • 1
  • 9
  • 22
0

Other solutions weren't working for me (I could input negative number from scrolling mouse wheel or trackpad), so I made a kind of hardcoded method:

onChange={function (event) {
  if (value > 0 || event.target.valueAsNumber >= 0) {
    setValue(event.target.valueAsNumber);
  }
}}
Chends
  • 1
0
<input type="number" onKeyDown={preventNegativeValues}/>

//function export

export const preventNegativeValues = (e) => ["e", "E", "+", "-"].includes(e.key) && e.preventDefault()
0

I prefer this answer as it has alot of functionality in one.
Use Math.sign() it has the following possible results:
it returns 1 if the argument is positive.
it returns -1 if the argument is negative
it returns 0 if the argument is 0
it returns -0 if the argument is -0
in all other cases it returns NaN (not a number)
example
if(Math.sign(somevalue)!=1){ console.log("please provide a valid number" } }

louis
  • 422
  • 1
  • 4
  • 14