1
votes

Currently, I have regex implemented where comma appears on every 3 digits entered in convertNumberToString prop. And convertStringToNumber prop simple removes the comma convert back to number type. I would like to update regex for convertNumberToString so that there is trailing 2 decimal and comma separator like currency format so if a user enter 12345.67 then 12,345.67 appears on the input field. And if user try to enter wrong format such as 123.45.678 or 123.5555 then it rejects. This is my current regex: replace(/(\d)(?=(\d\d\d)+(?!\d))/g, "$1,") How should I update the regex so it meets my desired requirement? https://codesandbox.io/s/number-field-currency-ts-kpylkw?file=/src/App.tsx

import React, { useState, useRef, useEffect } from "react";
import "./styles.css";

export interface NumberFieldInterface {
  convertStringToNumber?: (value: string) => number;
  convertNumberToString?: (value: number) => string;
  onChange?: (value: number) => void;
  value: number;
}

const NumberField = React.forwardRef<HTMLInputElement, NumberFieldInterface>(
  (props, ref) => {
    const {
      value,
      onChange,
      convertStringToNumber,
      convertNumberToString
    } = props;
    const inputRef = useRef(null);
    let convertedValue;

    const onValueChange = (value: string) => {
      if (typeof onChange === "function" && convertStringToNumber) {
        //console.log(typeof value);
        convertedValue = convertStringToNumber(value);
        // console.log(typeof convertedValue);
        const isNumber =
          typeof convertedValue === "number" && isFinite(convertedValue);

        if (isNumber) {
          onChange(convertedValue);
        }
      }
    };

    return (
      <div>
        <input
          type="text"
          ref={ref}
          value={convertNumberToString?.(value)}
          onChange={(e: React.FormEvent<HTMLInputElement>) =>
            onValueChange(e.currentTarget.value)
          }
        />
      </div>
    );
  }
);

export default function App() {
  const [inputValue, setInputValue] = useState<number>(123.45);
  const ref = useRef(null);

  const handleChange = (val: number) => {
    // console.log("Value of val is ", val);
    setInputValue(val);
  };

  useEffect(() => {
    // console.log("Type of inputValue is ", typeof inputValue);
  }, [inputValue]);

  return (
    <div className="App">
      <NumberField
        ref={ref}
        convertStringToNumber={(val) => {
          return +val.replace(/,/g, "");
        }}
        convertNumberToString={(val) => {
          return val.toString().replace(/(\d)(?=(\d\d\d)+(?!\d))/g, "$1,");
        }}
        value={inputValue}
        onChange={handleChange}
      />
    </div>
  );
}