2

Problem:

I have a controlled input, using Material-UI TextField. I want to have purely numbers, and support type="number" for mobile keyboards, but when having empty string as default, and having a parseInt in the onChange, it will not allow 0 (zero). All other numbers are displayed correctly.

It even correctly sets 0 in the underlying object bound to the TextField.

In other inputs i have default values as empty strings (heavily simplified), like shown:

<TextField
    name={"inputToBeSaved"}
    value={this.state.objectForSaving.inputToBeSaved|| ''}
    onChange={this.handleChange}
    variant="outlined"
/>

With corresponding handleChange:

handleInputChange(event) {
    const target = event.target;
    const value = target.value;
    const name = target.name;
    this.setState(prevState => ({
        objectForSaving: {
            ...prevState.objectForSaving,
            [name]: value
        }
    }))
}

The example above works as espected, but not when trying to work with numbers:

<TextField
    type="number"
    name={"numberToBeSaved"}
    value={this.state.objectForSaving.numberToBeSaved|| ''}
    onChange={this.handleChange}
    variant="outlined"
/>
handleChange(event) {
    const target = event.target;
    const value = target.type === 'checkbox' ? target.checked : target.type === 'number' ? parseInt(target.value) : target.value;
    const name = target.name;
    this.setState(prevState => ({
        objectForSaving: {
            ...prevState.objectForSaving,
            [name]: value
        }
    }))
}

I know that defaulting to 0, or making it uncontrolled will fix it, but some times I do have values there from the server, so I want to reuse the components.

I have tried to look at this post, but did not find any good solution to keep it controlled: Initializing React number input control with blank value?

3 Answers 3

2

0 is falsey, so in the following condition:

this.state.objectForSaving.numberToBeSaved|| ''

if numberToBeSaved is 0, then the expression will evaluate to empty string.

If you are just trying to check if numberToBeSaved is defined, then you can do this more robustly with:

this.state.objectForSaving.numberToBeSaved === undefined ? '' : this.state.objectForSaving.numberToBeSaved
Sign up to request clarification or add additional context in comments.

2 Comments

That was a perfect explanation. I testet a little and made a isUndefined helper-method. That solved my problem. Thank you.
If you happen to already be using lodash, you could use its isUndefined or isNil functions rather than duplicating these kind of helper methods in your own code.
0

You can convert the value to string when setting the TextField prop.

const {
  objectForSaving: {
    inputToBeSaved = '',
  },
} = this.state

<TextField
  name={"inputToBeSaved"}
  value={String(inputToBeSaved)}
  onChange={this.handleChange}
  variant="outlined"
/>

Comments

0

And if using formik, do it like this:

const formik = useFormik({
    initialValues: {
      inputToBeSaved: "",
      ...
    },
  });

  <TextField
    id="inputToBeSaved"
    name="inputToBeSaved"
    type={"number"}
    {...formik.getFieldProps("inputToBeSaved")}
    label={"input To Be Saved"}
    variant="outlined"
  />

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.