2

I want let users enter only integer or floating numbers. Right now I can only enter integer numbers,it does allow type dot or comma . Cant find proper regex to validate both integer and floating numbers.

<input
  type="text"
  id="depositedAmount"
  maxLength={9}
  placeholder="Enter amount"
  onChange={(e) => this.handleInputChange(e, currentComProfile)}
  value={depositedAmount}
/>

handleInputChange=(e, currentComProfile) => {
    const re = /^[+-]?\d+(\.\d+)?$/;

    if (e.target.value === '' || re.test(e.target.value)) {
      if (e.target.id === 'depositedAmount') {
        this.props.updateDepositedAmount(e.target.value, currentComProfile);
      }
      if (e.target.id === 'willBeCreditedAmount') {
        this.props.updateWillBeCreditedAmount(e.target.value, currentComProfile);
      }
    }
  }
Yerlan Yeszhanov
  • 2,149
  • 12
  • 37
  • 67
  • Regex you have is fine, and should work, can you be more specific where you're facing problem, and also you should use `type='number'` – Code Maniac Oct 17 '19 at 04:48

3 Answers3

1

You may use

const rx_live = /^[+-]?\d*(?:[.,]\d*)?$/;

for live validation. For the final validation, use

const rx_final = /^[+-]?\d+(?:[.,]\d+)?$/;

Or, better, just use the regex in the pattern attribute: pattern="[+-]?\d*(?:[.,]\d*)?".

NOTE

  • ^ - start of string
  • [+-]? - an optional + or -
  • \d* - 0 or more digits
  • (?:[.,]\d*)? - an optional sequence of . or , and then 0 or more digits
  • $ - end of string.

In final validation, \d+ is used instead of \d* to match one or more digits as opposed tozero or more digits.

See the JS demo:

const rx_live = /^[+-]?\d*(?:[.,]\d*)?$/;

class TestForm extends React.Component {
  constructor() {
    super();
    this.state = {
      depositedAmount: ''
    };
  }

  handleDepositeAmountChange = (evt) => {
    if (rx_live.test(evt.target.value))
        this.setState({ depositedAmount : evt.target.value });
 }
  
  render() {
    return (
      <form>
       <input
        type="text"
        id="depositedAmount"
        maxLength={9}
        pattern="[+-]?\d+(?:[.,]\d+)?"
        placeholder="Enter amount"
        onChange={this.handleDepositeAmountChange}
        value={this.state.depositedAmount}
       />
      </form>
    )
  }
}


ReactDOM.render( < TestForm /> , document.getElementById('app'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="app"></div>
Wiktor Stribiżew
  • 607,720
  • 39
  • 448
  • 563
0

Your regex should match dots, but it doesn't seem to match commas. You could try something like:

^[0-9]+([,.][0-9]+)?$

For reference:

[0-9] matches digits 0-9.

+ matches between one and unlimited times, as many times as possible.

[,.] matches comma or dot.

There might be a way to simplify this regex, but I think it should work.

You can test it here: https://regex101.com/r/V0J63U/1

--Update--

To match leading signs also (i.e., +/-), you can add ^[+-]? to the beginning of the pattern:

^[+-]?[0-9]+([,.][0-9]+)?$

You can test it here: https://regex101.com/r/cQylX3/1

Thank you to @CodeManiac for the tips!

JoshG
  • 6,472
  • 2
  • 38
  • 61
0
function App() {

    const [budget, setBudget] = useState(0);

    const handleKeyPress = (ev) => {
        let charC = (ev.which) ? ev.which : ev.keyCode;
        if(charC == 46) {
            if(ev.target.value.indexOf('.') === -1) {
                let caretPos = ev.target.selectionStart;
                if(caretPos <= (ev.target.value.length - 3)) {
                    ev.preventDefault();
                    return false;
                }
                return true;
            }
            else {
                ev.preventDefault();
                return false;
            }
        }
        else {
            if(charC > 31 && (charC < 48 || charC > 57)) {
                ev.preventDefault();
                return false;
            }
        }

        if(ev.target.value.indexOf('.') !== -1) {
            let numComp = ev.target.value.split('.');                    
            if(numComp[1].length > 1) {
                let caretPos = ev.target.selectionStart;
                let dotPos = ev.target.value.indexOf('.');
                if(caretPos <= dotPos) {
                    return true;
                }
                ev.preventDefault();
                return false;
            }
        }                
        return true;
    }

    const handleChange = (ev) => {
        setBudget(ev.target.value);
    }

    return (
        <div className="App">
            <div className="input-control">
                <label>
                    Iznos proračuna: 
                    <input 
                        type="text"
                        value={budget}
                        onKeyPress={(event) => handleKeyPress(event) }
                        onChange={(event) => handleChange(event)}
                    />
                </label>
            </div>
        </div>
    );
}
export default App;

Explanation: React is a bit different than 'pure' JavaScript. 'handlePress' function is like already suggested solutions in pure JavaScript but instead returning 'false' one should use ev.preventDefault() prior to returning false to prevent displaying unwanted characters. Displaying decimal dot is allowed only once in input field and input is limited to max 2 decimal places, so decimal point can be in front of max 2 last digits on the right. Code can be customized for other purposes as well :)

Dharman
  • 30,962
  • 25
  • 85
  • 135