P
P
Pavel M2022-01-28 23:36:29
React
Pavel M, 2022-01-28 23:36:29

How to change the type and value at the right moment?

good evening.

need help with input component.
what is at the moment
1) there is an input. By default, the type prop is set to number. in the onchange, the value is run through a regular expression that cuts off signs, and nothing is entered at the output except integers.
2) props with the maximum allowed number.
3) there are pseudo buttons + - that add\reduce value by some n-number.
4) if the number is large, like 1000000, then onBlur the value is converted to a string, commas are substituted and the value becomes 1,000,000. on OnFocus, respectively, it is again a number, and the commas disappear.

actually the task is - when clicking on + - I get into onblur and I can't decrement\increment because it's a string at that moment.
The only thing I thought of was switching to focus and zero timeout on blur, but it didn't work.

const Input = ({
  onChange,
  disabled,
  numStep = 1,
  min = 0,
  max,
  value,
  placeholder,
  className,
  type = 'number',
  onBlur,
  onFocus,


  isPriceInput
}) => {

  // STATES
  const [isFocused, setIsFocused] = useState(false);
  const [isEditing, setEditing] = useState(false);


  // HANDLES
  const handle = {
    change: (e) => {
      let inputValue = e.target ? onlyNumbers(e.target.value) : e;
      if (inputValue !== '') {
        // inputValue = inputValue.toString().replace(/\D/g, '');
        inputValue = parseFloat(inputValue) || '';
        if (min && +min > +inputValue) {
          inputValue = +min;
        } else if (max && +max < +inputValue) inputValue = +max;
      } 

      onChange(inputValue.toString());
    },
    toggleEdit: () => {
      setEditing(!isEditing);
      onChange('');
    },
    focus: (e) => {
      setIsFocused(true);
      if (isPriceInput) onChange(removeComma(value));

      if (onFocus) onFocus(e);
    },
    blur: (e) => {
        setIsFocused(false);
        setEditing(false);

        if (isPriceInput) onChange(addCommas(value));


      if (onBlur) onBlur(e);
    },

    decrement: () => {
 
      handle.change(+value - +numStep);
    },
    increment: () => {

      handle.change(+value + +numStep);
    }
  };

  useEffect(() => {
    if (isEditing || isFocused) inputRef.current.focus();
  }, [isEditing, isFocused]);

  const uniProps = {
    className: `input ${className}`,
    placeholder,
    value: value || '',
    disabled,
    onChange: handle.change,
    onFocus: handle.focus,
    onBlur: handle.blur,
    onKeyUp: handle.keyUp,
    min,
    max,
    ...(maskChar ? { maskChar } : {}),
    ...(formatChars ? { formatChars } : {})
  };

  return (
    <div className='input__wrap'>
      <input {...uniProps} ref={inputRef} type={type} />

      <div className='input__nums'>
        <button
          onClick={() => handle.decrement()}
          className={cn(`input__num-btn`, { disabled: value <= min })}
        >
          <Minus />
        </button>
        <button
          onClick={() => handle.increment()}
          className={cn(`input__num-btn`, { disabled: value >= max })}
        >
          <Plus />
        </button>
      </div>
    </div>
  );

 

export default Input;


addCommas: (value) => {
      value = value.toString();
      const isFraction = value.includes('.');

      const valueBeforeDot = isFraction
        ? value.slice(0, value.indexOf('.'))
        : value;

      const intPart = valueBeforeDot
        .split('')
        .reverse()
        .reduce(
          (acc, item, idx) =>
            idx % 3 === 0 && idx !== 0 ? [...acc, ',', item] : [...acc, item],
          []
        )
        .reverse()
        .join('');

      return isFraction ? intPart + value.slice(value.indexOf('.')) : intPart;
    },
    removeComma: (value) => {
      return parseFloat(value.replace(/\,/g, ''));
    }
  },
  onlyNumbers: (value, isDot = false) => {
    const val =
      value.slice(0, 1) !== '0' && value.slice(0, 1) !== '.'
        ? value
        : value.slice(1);
    if (isDot) return twoDigitAfterDot(val.replace(/[^0-9.]/g, ''));
    else return +val.toString().replace(/\D/g, '');
  },

Answer the question

In order to leave comments, you need to log in

1 answer(s)
A
Alexandroppolus, 2022-01-29
@Alexandroppolus

Inside increment and decrement use removeComma if there is a string.

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question