Put length constraint in a TextField in react js
Asked Answered
P

15

132

I am taking an input from the user of the card number and wants that the length entered by user must not be less than and more than 12. Here is the declaration of my textfield.

<TextField
    id="SigninTextfield"
    label="Aadhaar number"
    id="Aadhar"
    lineDirection="center"
    required={true}
    type="number"
    maxLength={12}
    style={styles.rootstyle}
    erorText="Please enter only 12 digits number"
/>

Now I am not understanding whether to use javascript or any event handler for restricting the length.

Prehensible answered 29/8, 2017 at 13:2 Comment(6)
From where are you using the TextField CompoenntNoah
@ShubhamKhatri from react-md/libPrehensible
I can't see any maxLength property material-ui.com/#/components/text-fieldSidoon
I was trying to implement the maxLength and forgot to remove it from code. @SidoonPrehensible
The maxLength property is present as a prop but doesn't limit the length of text rather displays a warning if the text exceeds the length, and shows the count on the side . react-md.mlaursen.com/components/text-fields?tab=1Noah
You might want to implement a controlled text field and limit the text size yourselfNoah
B
45

I found another solution here.

<TextField
    required
    id="required"
    label="Required"
    defaultValue="Hello World"
    onInput = {(e) =>{
        e.target.value = Math.max(0, parseInt(e.target.value) ).toString().slice(0,12)
    }}/>
Burble answered 6/3, 2018 at 11:54 Comment(3)
Absolutely, the right way is using inputProps but if the input type is number your way is the proper way.Commonality
onInput = {(e) =>{ var InputElement = (e.target as HTMLInputElement); InputElement.value = Math.max(0, parseInt(InputElement.value) ).toString().slice(0,12); }} in my environment .value is not recognised, so used HTMLInputElement.Swelter
if the value starts with 0 ,this does not work, my solution is, e.target.value = e.target.value.toString().slice(0, 6);Dodgem
P
304

You can set the maxLength property for limiting the text in text box.

Instead of onChange method you can pass maxLength to the inputProps (lowercase i, not InputProps) props of material-ui TextField.

<TextField
    required
    id="required"
    label="Required"
    defaultValue="Hello World"
    inputProps={{ maxLength: 12 }}
/>

Basically we can edit all input element's native attrs via inputProps object.

Link to TextField Api

Pedropedrotti answered 24/1, 2018 at 5:30 Comment(8)
this isn't a feature, there is only inputStyleParathion
Warning: Mind the lowercase i in "inputProps", which is totally different with "InputProps" with uppercase I. I learnt it the hard way.Hanlon
Why does maxLength alone not work? I've seen a lot of maxLength answers, but only this solves the problem?Daviddavida
@Daviddavida maxLength alone doesn't work simply because the <TextField> does not support this propSelfabasement
Warning! This doesn't work with type="number"Brigadier
this doesn't work on <Input> fields if it's set to type="number"Delora
This works on these types: password, search, tel, text, url, email. RefVituline
InputProps applies to Input react-component since TextField is composed of smaller components. inputProps applies to what will be input DOM-element and it gets all of its attributes.Disturbing
B
45

I found another solution here.

<TextField
    required
    id="required"
    label="Required"
    defaultValue="Hello World"
    onInput = {(e) =>{
        e.target.value = Math.max(0, parseInt(e.target.value) ).toString().slice(0,12)
    }}/>
Burble answered 6/3, 2018 at 11:54 Comment(3)
Absolutely, the right way is using inputProps but if the input type is number your way is the proper way.Commonality
onInput = {(e) =>{ var InputElement = (e.target as HTMLInputElement); InputElement.value = Math.max(0, parseInt(InputElement.value) ).toString().slice(0,12); }} in my environment .value is not recognised, so used HTMLInputElement.Swelter
if the value starts with 0 ,this does not work, my solution is, e.target.value = e.target.value.toString().slice(0, 6);Dodgem
S
24
    <TextField
      autoFocus={true}
      name="name"
      onChange={handleChange}
      placeholder="placeholder"
      id="filled-basic"
      variant="filled"
      size="small"
      fullWidth
      inputProps={{
        maxLength: 25,
      }}
      InputProps={{
        startAdornment: (
          <InputAdornment position="start">
            <SearchIcon />
          </InputAdornment>
        ),
      }}
    />
Sisterinlaw answered 29/9, 2020 at 20:44 Comment(2)
thank you, this worked for me while working with adornmentsSuite
I've also added this for eslint warning: // eslint-disable-next-line react/jsx-no-duplicate-propsPruritus
D
11
      <TextField
        id="username"
        name="username"
        label={translate('username')}
        onChange={handleChange}
        onBlur={handleBlur}
        value={values.username}
        error={Boolean(errors.username) && touched.username}
        helperText={(errors.username && touched.username && translate(errors.username))}
        required
        inputProps={{maxLength :20}}

      />
Dogberry answered 12/3, 2020 at 13:53 Comment(0)
C
8

Is it worth noting that Material-ui <TextField /> component doesn not have a maxlength property. However, the original html <input> does. So you don't really need to create any extra function to get this to work. Just use the base <input> attributes using inputProps.

The actual answer is this:

inputProps={
    {maxLength: 22}
}
// Result => <input maxlength="yourvalue" />

What this does is it sets the maxlength attribute of the underlying <input> resulting in: <input maxlength="yourvalue" />. Another important thing to note here is that you use inputProps and not InputProps. The one you're targeting is the small letter inputProps.

Checkoff answered 19/9, 2020 at 21:19 Comment(0)
V
7

If you're using MUI 5, version 5.0.6, due to a support for legacy, you will have to do something like this,

            <TextField
              id="standard-textarea"
              label="A label"
              placeholder="Some text here"
              multiline
              variant="standard"
              defaultValue={"Hello"}
              inputProps={{
                maxLength: 255,
              }}
              InputProps={{
                disableUnderline: true,
              }}
            />

The TextField supports both inputProps and InputProps, but some properties don't work vice versa.

maxLength does not work as expected in InputProps, and a property like disableUnderline for the MUI 5 does not work as expected in inputProps.

Be careful with a possible typo with the i.

See the API for more information, https://mui.com/api/text-field/.

Vipul answered 10/1, 2022 at 9:9 Comment(0)
N
6

I discovered something weird on the behavior between TextField and Input from Material UI

They are very similar to each other, the problem I see is the following:

On the TextField component, if you use InputProps with capital "I", the Adorments are shown, but in the other hand if you use it as lowercase "inputProps", the maxLength Html attribute is TAKEN as valid, but not the adorments

I ended up using INPUT instead of a TextField so you can use adorments in

               <TextField
                variant="outlined"
                required
                fullWidth
                error={errors.email}
                id="email"
                label={t("signup-page.label-email")}
                name="email"
                onChange={handleChange}
                inputProps={{
                  endAdornment: (
                    <InputAdornment position="end">
                      <IconButton aria-label="toggle password visibility">
                        <EmailIcon />
                      </IconButton>
                    </InputAdornment>
                  ),
                  maxLength: 120,
                }}
              />

in the above code the adorment is ignored, but maxLength taken used as "inputProps" camel case

The below code is a working example, as you might see, I embraced it as in the old style within a Form Control, the input label and the input "outlinedInput"

        <FormControl variant="outlined" fullWidth>
        <InputLabel htmlFor="firstName">Password</InputLabel>
        <OutlinedInput
          value={values.firstName}
          autoComplete="outlined"
          name="firstName"
          variant="outlined"
          required
          fullWidth
          error={errors.firstName}
          id="firstName"
          label={t("signup-page.label-firstname")}
          onChange={handleChange}
          autoFocus
          inputProps={{ maxLength: 32 }}
        />
      </FormControl>

Solution. My final recommendation, use an OutlinedInput instead of a TextField, so you can put in a separated way Adorments and also maxLength

Below a working example with FormControl OutlinedInput, inputProps - maxLength and an end Adorment Icon

      <FormControl variant="outlined" fullWidth>
        <InputLabel htmlFor="password">Password</InputLabel>
        <OutlinedInput
          value={values.passwordConfirm}
          variant="outlined"
          required
          fullWidth
          error={errors.passwordConfirm}
          name="passwordConfirm"
          label={t("signup-page.label-password-confirm")}
          type={values.showPasswordConfirm ? "text" : "password"}
          id="password-confirm"
          onChange={handleChange}
          inputProps= {{maxLength:32}}
          endAdornment= {
              <InputAdornment position="end">
                <IconButton
                  aria-label="toggle password visibility"
                  onClick={handleClickShowPassword("passwordConfirm")}
                  onMouseDown={handleMouseDownPassword}
                >
                  {values.showPasswordConfirm ? (
                    <Visibility />
                  ) : (
                    <VisibilityOff />
                  )}
                </IconButton>
              </InputAdornment>
          }
        />
        {errors.passwordConfirm && (
          <p className="error"> {errors.passwordConfirm} </p>
        )}
      </FormControl>
Northeaster answered 12/4, 2020 at 20:27 Comment(2)
You are true, InputProps adds props to its parent container div.Swearword
Keep in mind. The first example in this answer provides endAdornment as a prop of inputProps - this is a mistake. it should be InputPropsRedletter
B
4

The accepted answer won't work in Firefox for large numbers (greater than 16 digits). Numbers just behaves in a weird way.

For a 22 length field we ended up using this:

<TextField
  required
  validateOnBlur
  field="cbu"
  label="22 dígitos del CBU"
  validate={validate.required}
  type="text"
  inputProps={
    {maxLength: 22}
  }
  onInput={(e) => { e.target.value = e.target.value.replace(/[^0-9]/g, '') }}

/>

Basically, native maxLength constraint for text fields, plus a conversion from string to numbers "on the fly".

Improvement

Also you may prefer to make this reusable and more semantic.

# constraints.js
const onlyNumbers = (e) => { e.target.value = e.target.value.replace(/[^0-9]/g, '') };

# form.js
<TextField
  field="cbu"
  label="22 dígitos del CBU" 
  inputProps={
    {maxLength: 22}
  }
  onInput={(e) => onlyNumbers(e) }
Balfour answered 21/11, 2018 at 17:36 Comment(0)
S
2

The material-design <TextField /> component haven't any length property.

You can create yours in the onChange() method.

updateTextField(event,value){
  if(value.length <= 12){
     //Update your state
  }
  else{
    //Value length is biggest than 12
  }
}

<TextField
    id="SigninTextfield"
    label="Aadhaar number"
    id="Aadhar"
    lineDirection="center"
    required={true}
    type="number"
    onChange={(e,v) => this.updateTextField(e,v)}
    style={styles.rootstyle}
    erorText="Please enter only 12 digits number"
/>
Sidoon answered 29/8, 2017 at 13:14 Comment(0)
F
1

In your change handler, just write.

if (event.target.value.length !== maxLength ) return false; 
Fagaceous answered 28/7, 2021 at 14:25 Comment(0)
D
1

I had a similar issue, but with TextareaAutosize. Unfortunately,

inputProps={{ maxLength: 12 }}

doesn't work with TextareaAutosize.

The below workaround works for TextareaAutosize and for both text and numbers. Inspired by the accepted answer to this question - https://mcmap.net/q/172466/-put-length-constraint-in-a-textfield-in-react-js

onInput = {(e) =>{
    e.target.value = (e.target.value).toString().slice(0,10)

import * as React from 'react';
import TextareaAutosize from '@mui/material/TextareaAutosize';

export default function MinHeightTextarea() {
  return (
    <TextareaAutosize
      aria-label="minimum height"
      minRows={3}
      placeholder="Minimum 3 rows"
      style={{ width: 200 }}
      onInput = {(e) =>{
        e.target.value = (e.target.value).toString().slice(0,10)
    }}
        
    />
  );
}

Link to demo: Limiting character length in MUI TextareaAutosize

Displayed answered 24/3, 2022 at 17:10 Comment(0)
F
1
<TextField
id="SigninTextfield"
label="Aadhaar number"
id="Aadhar"
lineDirection="center"
required={true}
type="number"
inputProps={{
maxLength: 20,
}}
style={styles.rootstyle}
erorText="Please enter only 12 digits number"
/>
Furculum answered 27/9, 2022 at 8:26 Comment(1)
note to readers, it is inputProps, (smaller i) and not InputProps (i.e. capital I)Girvin
Z
1

We can set using inputProps property in the following way

import React from 'react'
import { Autocomplete, TextField } from '@mui/material'


export default function Select({
    onChangeInput,
    label,
    name,
    value,
    options,
    placeholder,
    disabled,
    error,
    helpertext,
    required,
    shrink,
    maxLength
}) {

    const _onChange = (e, v) => {
        onChangeInput(v)
    }

    return (
        <Autocomplete
            freeSolo
            fullWidth={true}
            multiple={false}
            margin={'noraml'}
            readOnly={disabled}
            name={name}
            isOptionEqualToValue={(option, value) => option.label === value.label}
            value={value}
            options={options}
            placeholder={placeholder}
            renderInput={params => (
                <TextField {...params}
                    label={label}
                    error={error}
                    required={required}
                    helperText={helpertext}
                    variant={'standard'}
                    inputProps={{ ...params.inputProps, maxLength: (maxLength && parseInt(maxLength)) || 99}}
                    InputLabelProps={{ shrink: shrink, style: { fontSize: 18 } }}
                />
            )}
            onInputChange={_onChange}
        />
    )
}
Zielinski answered 23/11, 2023 at 13:0 Comment(0)
A
0

For people who still are looking for a solution for the number field, this solution worked fine for me.

onInput={(e: any) => {
                  e.target.value = Math.max(0, parseInt(e.target.value))
                    .toString()
                    .slice(0, 2);
                }}

Make sure to use any.

Ancestry answered 7/12, 2022 at 19:0 Comment(0)
M
0

import * as React from "react";
import Box from "@mui/material/Box";
import TextField from "@mui/material/TextField";

export default function BasicTextFields() {
  const [num, setNum] = React.useState();
  const limitChar = 12;
  const handleChange = (e) => {
    if (e.target.value.toString().length <= limitChar) {
      setNum(e.target.value);
    }
  };

  return (
    <Box component="form">
      <TextField
        type="number"
        id="outlined-basic"
        label="Outlined"
        variant="outlined"
        onChange={(e) => handleChange(e)}
        defaultValue={num}
        value={num}
      />
    </Box>
  );
}
Melia answered 2/6, 2023 at 6:14 Comment(1)
Your answer could be improved with additional supporting information. Please edit to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers in the help center.Elurd

© 2022 - 2024 — McMap. All rights reserved.