Closed skorphil closed 6 months ago
Some native features of use-hook-form: https://react-hook-form.com/advanced-usage#TransformandParse
They utilize controller
, but i use register
as recommended in chackra UI docs https://chakra-ui.com/getting-started/with-hook-form
However controller
and register
have different methods https://github.com/orgs/react-hook-form/discussions/11538
and to update the value of register
ed component, the setValue()
method should be used. Async nature of setValue()
causing unwanted carret jump: https://github.com/skorphil/nextjs-form/issues/38#issuecomment-1973532662
I need to caver range of scenarios. 1,000.00 for fiat 1,000.xxxxxxx... for crypto
Additional scenario problem: 1,000.
being converted to 1,000
so it is impossible to add fractoring digits if it wasn't formatted like so
Also the problem appears with jumping cursor during input
Scenario of removing last remaining number
ChackraUI NumberInput
not working with locale strings. Need to use Input
Input
to make it numerical (mobile keyboard numerical)Additional scenario problem:
1,000.
being converted to1,000
so it is impossible to add fractoring digits if it wasn't formatted like so
Made regex to capture zeros (?<!\..*)\.0*(?![0-9])
regexr.com/7sqjq
Another problem is JS float precision.
0.00065934
NumberFormat()
and toLocaleString()
both failingconst number = 0.00065934
const numForm = Intl.NumberFormat().format(number) // 0.001
const toLoc = number.toLocaleString() // 0.001
numeral.js increases formatting accuracy to parseFloat()
const numString = "0.123456789123456789"
const parseFl = parseFloat(numString) // '0.12345678912345678'
const number = 0.123456789123456789
const numForm = Intl.NumberFormat().format(number) // 0.123
const toLoc = number.toLocaleString() // 0.123
const numeralVar = numeral(number).format('0.[00000000000000000]') // '0.12345678912345678'
for more accuracy https://www.npmjs.com/package/decimal.js/v/3.0.0
The more complex problem to deal with is carret jumping after updating value with:
<Input
{...register(`${assetName}.amount`, {
onChange: (e) => {
const numberFormatted = stringToNumberFormatLocale(
e.target.value
);
setValue(`${assetName}.amount`, numberFormatted); // async function, so carret position resets
},
})}
/>
https://github.com/skorphil/nextjs-form/assets/6762009/e68ac433-df43-48ad-8bc4-45ff0ecef928
Might be better to use external libraries for some sort of masks
BTW Mantine UI inputs supports this natively
Under the hood it uses react-number-format https://github.com/mantinedev/mantine/blob/master/packages/%40mantine/core/src/components/NumberFormatter/NumberFormatter.tsx
Here is an article how to combine all the libraries (chakra, react-number-format and react-hook-form) https://medium.com/@roquejr1307/chakra-form-hook-number-format-73ff9ed6f84
With a good explanation of hook-form's Controller
. The author uses Controller
for masked input and register
for unmasked
In the article legacy number-format is used https://s-yadav.github.io/react-number-format/docs/migration
Well, solved number formatting issue with a more complex approach with react-number-format https://codesandbox.io/p/devbox/input-format-chakra-ui-form-hook-number-format-forked-wpdpjw
Similar to:
37
Need to transform numbers inside inputs.
10000
->10,000
or10 000
Need support for floating values (i.e. for crypto)0.00065934