reactjstypescriptbootstrap-5user-inputreact-bootstrap

Unable to input negative sign in input field


I am new to React and I am trying to have a input field which can take values between -40 and 30. I am using Form.Control from react-bootstrap and below is my code

interface Range{
 min: number,
 max: number
}

const defaultState : types.EqParamRange = {
   Max: 0,
   Min: -1,
};

const [stateRange, setRange] = React.useState<types.Range>(defaultState);

<Form.Group
    key="min"
    className="mb-3"
   >
   <Form.Label>Y-min</Form.Label>
   <Form.Control
        type='number'
        disabled={!enableCustomAxis}
        min={-40}
        max={30}
        step={1}
        value={Range.Min}
        onChange={(event) => {
            const target = event.target as HTMLInputElement
            const value = Number(target.valueAsNumber);
             setCustomYAxisRange( Range => ({
                    ...Range,
                    Min: value
                }));                            
        }}  
        required          
        placeholder='Enter minimum value of Y-coordinate'>
    </Form.Control>
</Form.Group> 

On clearing the input field, when I try to input minus sign, it does not allow me to do so. How do I resolve this?

I tried using type='text' and pattern which allows negative numbers but it does not work


Solution

  • It's one of the quirks of controlled inputs in React.

    When the user types "-", the code then tries to get the valueAsNumber which returns NaN - not a valid number, and so the input isn't allowed, just as if you tried to enter letters.

    The answer is to deal with values entered as if they're strings, run some validation, and then when you have a number, update Range

    So handling the event as below allows an empty string, a dash, or a negative number as being valid, and anything else is ignored.

     const handleMinChange = (event) => {
        const inputValue = event.target.value;
    
        // Allow empty string or a valid number string (including negative numbers)
        if (inputValue === '' || /^-?\d+$/.test(inputValue)) {
          setRange((prevRange) => ({
            ...prevRange,
            Min: inputValue,
          }));
        }
      };
    

    Your form input will still be of type number -- it's just the validation that's treating things as text.