React: Number input with no negative, decimal, or zero value values React: Number input with no negative, decimal, or zero value values reactjs reactjs

React: Number input with no negative, decimal, or zero value values


If you did it as a controlled input with the value in component state, you could prevent updating state onChange if it didn't meet your criteria. e.g.

class PositiveInput extends React.Component {    state = {        value: ''    }    onChange = e => {        //replace non-digits with blank        const value = e.target.value.replace(/[^\d]/,'');        if(parseInt(value) !== 0) {            this.setState({ value });        }    }    render() {        return (            <input               type="text"               value={this.state.value}              onChange={this.onChange}            />        );     }}


Here's a number spinner implantation in React Bootstrap. It only accepts positive integers and you can set min, max and default values.

class NumberSpinner extends React.Component {  constructor(props, context) {    super(props, context);    this.state = {      oldVal: 0,      value: 0,      maxVal: 0,      minVal: 0    };    this.handleIncrease = this.handleIncrease.bind(this);    this.handleDecrease = this.handleDecrease.bind(this);    this.handleChange = this.handleChange.bind(this);    this.handleBlur = this.handleBlur.bind(this);  }  componentDidMount() {    this.setState({      value: this.props.value,      minVal: this.props.min,      maxVal: this.props.max    });  }  handleBlur() {    const blurVal = parseInt(this.state.value, 10);    if (isNaN(blurVal) || blurVal > this.state.maxVal || blurVal < this.state.minVal) {      this.setState({        value: this.state.oldVal      });      this.props.changeVal(this.state.oldVal, this.props.field);    }  }  handleChange(e) {    const re = /^[0-9\b]+$/;    if (e.target.value === '' || re.test(e.target.value)) {      const blurVal = parseInt(this.state.value, 10);      if (blurVal <= this.state.maxVal && blurVal >= this.state.minVal) {        this.setState({          value: e.target.value,          oldVal: this.state.value        });        this.props.changeVal(e.target.value, this.props.field);      } else {        this.setState({          value: this.state.oldVal        });      }    }  }  handleIncrease() {    const newVal = parseInt(this.state.value, 10) + 1;    if (newVal <= this.state.maxVal) {      this.setState({        value: newVal,        oldVal: this.state.value      });      this.props.changeVal(newVal, this.props.field);    };  }  handleDecrease() {    const newVal = parseInt(this.state.value, 10) - 1;    if (newVal >= this.state.minVal) {      this.setState({        value: newVal,        oldVal: this.state.value      });      this.props.changeVal(newVal, this.props.field);    };  }  render() {    return ( <      ReactBootstrap.ButtonGroup size = "sm"      aria-label = "number spinner"      className = "number-spinner" >      <      ReactBootstrap.Button variant = "secondary"      onClick = {        this.handleDecrease      } > - < /ReactBootstrap.Button> <      input value = {        this.state.value      }      onChange = {        this.handleChange      }      onBlur = {        this.handleBlur      }      /> <      ReactBootstrap.Button variant = "secondary"      onClick = {        this.handleIncrease      } > + < /ReactBootstrap.Button> < /      ReactBootstrap.ButtonGroup >    );  }}class App extends React.Component {  constructor(props, context) {    super(props, context);    this.state = {      value1: 1,      value2: 12    };    this.handleChange = this.handleChange.bind(this);  }   handleChange(value, field) {    this.setState({ [field]: value });  }  render() {    return (       <div>        <div>Accept numbers from 1 to 10 only</div>        < NumberSpinner changeVal = {          () => this.handleChange        }        value = {          this.state.value1        }        min = {          1        }        max = {          10        }        field = 'value1'         / >         <br /><br />        <div>Accept numbers from 10 to 20 only</div>        < NumberSpinner changeVal = {          () => this.handleChange        }        value = {          this.state.value2        }        min = {          10        }        max = {          20        }        field = 'value2'         / >       <br /><br />      <div>If the number is out of range, the blur event will replace it with the last valid number</div>               </div>);  }}ReactDOM.render( < App / > ,  document.getElementById('root'));
.number-spinner {  margin: 2px;}.number-spinner input {    width: 30px;    text-align: center;}
<script src="https://unpkg.com/react@16/umd/react.development.js" crossorigin></script><script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js" crossorigin></script><script src="https://unpkg.com/react-bootstrap@next/dist/react-bootstrap.min.js" crossorigin></script><link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/latest/css/bootstrap.min.css" crossorigin="anonymous"><div id="root" />


That's how number input works. To simplify the code you could try to use validity state (if your target browsers support it)

onChange(e) {    if (!e.target.validity.badInput) {       this.setState(Number(e.target.value))    }}