Set min/max on TextField type="number"?
Asked Answered
B

10

130

I'm using Material-UI v1.0.0-beta23 along with redux-form and redux-form-material-ui. I have a Field that is type number and I want to set the min and max values on the tag. I've tried both inputProps and min/max and neither seem to do what I want. I looked at the source code and don't see an obvious way to do this. Is it possible, and if so, how?

Here is my JSX showing things I've tried.

<Field
  name="maxNodeSelectedCount"
  component={TextField}
  label="Max Node Selected Count"
  type="number"
  inputProps={{ min: 0, max: 10 }}
  min={11}
  max={20}
  format={formatOption}
  normalize={normalizeOption}
  {...propertyFieldDefaults}
/>

Here is what the DOM looks like:

<input type="number" class="MuiInput-input-346 MuiInput-inputSingleline-349 MuiInput-inputDense-347" value="-3" name="options.maxNodeSelectedCount">
Braque answered 13/12, 2017 at 16:37 Comment(0)
A
155

The redux-form Field will pass props through to the component:

All other props will be passed along to the element generated by the component prop.

The TextField has a property named InputProps which can be used to pass props to the Input component it renders. This is also true if you're using redux-form-material-ui. Its TextField is simply a wrapper for the material-ui component.

The material-ui Input component has a property named inputProps which can be used to pass props to the input element it renders.

Ok, so what do I do?

You need to pass props all the way through, from Field, to TextField, to Input, to the input element.

So if we set InputProps on Field, it will be passed to TextField, which will pass it to the Input component. If the object we pass contains an inner inputProps (intentional lowercase 'i'), the Input component will pass it to the input element.

A game of hot-proptato:

Basically, define an inputProps object within InputProps and apply it to Field:

<Field
    name="maxNodeSelectedCount"
    component={TextField}
    label="Max Node Selected Count"
    type="number"
    InputProps={{ inputProps: { min: 0, max: 10 } }}
    format={formatOption}
    normalize={normalizeOption}
    {...propertyFieldDefaults}
  />
  • Field passes InputProps to TextField
  • TextField passes the contents of InputProps to the Input component
  • Input passed the contents of inputProps to the input element

There is a caveat with this:

The current implementation of TextField sets its own value for inputProps so that the inputClassName is applied to the input element.

By handing your own value of inputProps to TextField, you will overwrite the version applied by TextField, leaving inputClassName unset. If are using inputClassName you will need to include it in the inner inputProps object.

EDIT: I have submitted an issue and pull request to address this caveat in a future release.

Abott answered 13/12, 2017 at 17:11 Comment(5)
Adding the props like this didn't work either: props={{ InputProps: { min: 0, max: 10 } }} Now TextField is from redux-form-material-ui and not material-ui and I don't know if that matters.Braque
Sorry, I've updated my answer. The change from inputProps to InputProps is a breaking change relased with 1.0.0-beta.23.Abott
Thanks Ken for your help but I'm still having no luck. So do you think with beta 23 that InputProps should work? I even put a data property and nothing of these show up in the <input> DOM. InputProps={{ min: 0, max: 10, 'data-action': 'Hello' }} is rendering as <input type="number" class="MuiInput-input-246 MuiInput-inputSingleline-249 MuiInput-inputDense-247" value="" name="options.maxNodeSelectedCount">. I'm new to React and wondering if there is an online fiddle/sandbox that I can import my libraries to show the problem online?Braque
@MikeSuiter Just updated the answer. I missed the fact that Input and input are different! TextField wraps Input, which is another material-ui component that wraps the actual input DOM element.Abott
@MikeSuiter glad to help. I just submitted a PR to address the issue I've mentioned.Abott
C
85

Simply use your inputprops well

<TextField 
    type="number"
    InputProps={{
        inputProps: { 
            max: 100, min: 10 
        }
    }}
    label="what ever"
/>

notice the upper and lower case in the inputprops

credit to Ken Gregory

Contortionist answered 26/1, 2020 at 11:15 Comment(7)
} is missing after min : 10Grease
<TextField type="number" InputProps={{ inputProps: { max: 100, min: 10 } }} label="what ever"> </TextField>Settee
@Karan, sorry I don't get you, what do you mean?Contortionist
Jesus this is insaleny complicated for something so simple. Thanks for the working solution though.Departed
I'm happy to helpContortionist
@Departed you don't have to pass inputProps inside InputProps. Just pass it directly to the TextField. See this answer.Cattish
However, users can still enter values beyond the allowed rangeFranko
C
27

You can use inputProps to apply any attributes to the native input element, including min and max.

<TextField type="number" inputProps={{ min: 4, max: 10 }} />

Please note that the min/max attributes do not prevent the user from typing invalid values in the TextField. To restrict what the user can type, you can validate the value by adding onChange handler like below:

const min = 0;
const max = 10;

export default function BasicTextFields() {
  const [value, setValue] = useState<number>();

  return (
    <div>
      <TextField
        type="number"
        inputProps={{ min, max }}
        value={value}
        onChange={(e) => {
          var value = parseInt(e.target.value, 10);

          if (value > max) value = max;
          if (value < min) value = min;

          setValue(value);
        }}
      />
    </div>
  );
}

Edit 47798104/set-min-max-on-textfield-type-number

Cattish answered 13/4, 2021 at 10:0 Comment(1)
This works really well and adds to the above accepted answer!Unitary
F
4

Put type inside InputProps:

      <Field
        name="number"
        label="Number"
        component={TextField}
        InputProps={{
          inputProps: {
            type: 'number',
            min: 0, max: 25,
          },
        }}
      />
Fiord answered 21/6, 2021 at 11:57 Comment(0)
C
2

The other answers didn't work for me.

Material UI has a section for 3rd party integration here

It really does the job of writing only numbers and not allowing negatives.

import NumberFormat from 'react-number-format';

function NumberFormatCustom(props) {
    const { inputRef, onChange, ...other } = props;
    
     return (
            <NumberFormat
                {...other}
                getInputRef={inputRef}
                allowNegative={false}
                onValueChange={(values) => {
                    onChange({
                        target: {
                            name: props.name,
                            value: values.value,
                        },
                    });
                }}
                isNumericString
            />
        );
}
    
<TextField
    label="react-number-format"
    value={values.numberformat}
    onChange={handleChange}
    name="numberformat"
    id="formatted-numberformat-input"
    InputProps={{
          inputComponent: NumberFormatCustom,
     }}
/>
Closegrained answered 21/10, 2020 at 20:20 Comment(0)
H
1

If you are using rect hook form you can validate things like so:

import {Controller } from 'react-hook-form'
import {
  Box,
  TextField,
  FormHelperText,
  FormControl,

} from '@mui/material'
...
const {
  handleSubmit,
  control,
  formState: { errors },
} = useForm({})
...
<Box mt={2}>
  <Controller
    name="weight"
    control={control}
    rules={{
      required: 'Veuillez choisir une réponse',
      validate: {
        weight: (value) =>
          value < 1 || value > 5
            ? 'Le poids doit etre entre 1 et 5'
            : undefined,
      },
    }}
    render={({ field: { onChange, value } }) => (
      <FormControl fullWidth>
        <TextField
          type="number"
          value={value}
          onChange={onChange}
          label="Poids"
          name="weight"
        />
      </FormControl>
    )}
  />
  <FormHelperText error={Boolean(errors.weight)}>
    {errors.weight?.message}
  </FormHelperText>
</Box>

enter image description here

Hurlow answered 28/12, 2022 at 12:40 Comment(0)
P
1
 type="number"
 InputProps={{
                inputProps: { 
                    max: 14 , min: 0.1 , step: "0.1"
                }
            }}

you can enter decimal value as well using this

Preconcerted answered 12/2 at 18:34 Comment(0)
N
0

This will definitely work

handleMobileNumber = (e) => {
 if (e.target.value.split("").length <= 10) {
  this.setState({
    mobileNumber: e.target.value,
  });
 }
};

<TextField
  label="Enter Mobile Number"
   variant="outlined"
   value={this.state.mobileNumber}
   onChange={this.handleMobileNumber}
   type="number"
/>
Nonfiction answered 16/4, 2021 at 3:55 Comment(0)
O
0

I had the same issue, in my case I wanted to prevent the user from adding very big or minus numbers in a MUI Textfield used for minutes or hours inputs.

My solution is the following:
In the MUI TextField

  <TextField                                                            
    type={'number'}
    helperText={'minutes'}
    defaultValue={minutes}
    onChange={(e) => { checkMinutesValidity(e) }}
  />

In the checkMinutesValidity function

  const checkMinutesValidity = (event) => {
    if(event.target.value > 59){
      event.target.value = 59;
    }
    if(event.target.value < 0){
      event.target.value = 0;
    }
}

Hope it helps.

Overnight answered 4/11, 2022 at 13:8 Comment(0)
S
-1
<TextField
            label="Username"
            id="outlined-start-adornment"
            variant="outlined"
            inputProps={{minlength:5, maxLength: 20}}
          />
Sayed answered 5/2, 2021 at 19:29 Comment(2)
The community encourages adding explanations alongisde code, rather than purely code-based answers (see here).Disaccustom
Hello and welcome to SO! While this code may answer the question, providing additional context regarding how and/or why it solves the problem would improve the answer's long-term value. Please read the tour, and How do I write a good answer?Orthicon

© 2022 - 2024 — McMap. All rights reserved.