简体   繁体   中英

React-Number-Format pass value as float to validation

I have a react-hook-form form and yup validation. What I'm trying to do is to format an input with react-number-format but also to pass float value to validation and to submit.

Here's the codesandbox: https://codesandbox.io/s/keen-field-26ub7

In InvoiceData.js there is an input that react-number-format is using. I would like to validate this input against the value above that (grossValue) but I think I cannot do this without parsing the value to float back again.

First solution

Create a NumberFormat class inside of InvoiceData and use the same formatting props, to retrieves its removeFormatting function

InvoiceData.js

const getProperties = ({ invoice, register, errors }) => ({
  customInput: TextField,
  inputRef: register,
  variant: "outlined",
  name: "amountToPay",
  label: "InvoiceData.amountToPay",
  helperText: ((errors || {}).amountToPay || {}).message,
  error: (errors || {}).amountToPay,
  thousandSeparator: " ",
  suffix: " PLN",
  defaultValue: (invoice || {}).amountToPay,
  decimalScale: 2,
  fixedDecimalScale: true
});

export const removeFormatting = (value, props = {}) => {
  const properties = getProperties(props);
  let res = Number.parseFloat(
    new NumberFormat(properties).removeFormatting(value)
  );
  if (properties.decimalScale) {
    return res * Math.pow(10, -properties.decimalScale);
  }
  return res;
};

You can then use that function to check if your submitted form is valid:

Form.js

const onSubmit = async (data) => {
  if (removeFormatting(data.amountToPay) === responseData.amountGross) {
    // action when valid
    console.log("valid");
  } else {
    // action when invalid
  }
};

see your modified code using this link: https://codesandbox.io/s/heuristic-paper-4ycuh

Second solution

Use a state to remember the amountToPay such as follow:

const [amountToPay, setAmountToPay] = useState(responseData.amountToPay)

Add a callback function to your InvoiceData component and use onValueChange from NumberFormat to call that function, eg :

const InvoiceData = ({...props, handleChanged} => {

  return (
    <NumberFormat
      // whatever props you need
      onValueChange={(value) => handleChanged(value.floatValue)}
    />
  );

}

You can then pass on the setAmountToPay that we defined previously, and pass it to InvoiceData in that manner:

<InvoiceData
  // whatever props you need
  handleChanged={setAmountToPay}
/>

You can then validate your submit as follow

const onSubmit = async () => {
  if (amountToPay === responseData.amountGross) {
    // action when valid
    console.log("valid");
  } else {
    // action when invalid
  }
};

I think I've found an answer building on top of what Alexandre ELIOT did in the second solution. Instead of passing amountToPay to onSubmit function I've passed it to the NumberFormat itself.

<NumberFormat
        customInput={TextField}
        inputRef={register}
        variant="outlined"
        name="amountToPay"
        label={t('InvoiceData.amountToPay')}
        helperText={
          /* eslint-disable-next-line */
          amountToPay> invoice.amountGross
            ? 'cannot be greater that amount gross'
            : amountToPay=== 0
            ? 'cannot be 0'
            : null
        }
        error={amountToPay> invoice.amountGross || amountToPay=== 0}
        thousandSeparator={' '}
        suffix=" PLN"
        defaultValue={invoice.amountToPay}
        onValueChange={(value) => handleValueChange(value.floatValue)}
        decimalScale={2}
        fixedDecimalScale
      />

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM