Consider the following input value:
12345
The output would be:
$ 123.45 instead of $ 1,2345.00.
How to achieve the first output using this library?
This is how I am using right now, unfortunately I couldn't make it work as desired:
<NumberFormat
customInput={Input}
decimalScale={2}
decimalSeparator=","
fixedDecimalScale
onKeyDown={onEnter(handleEnter)}
onValueChange={handleValueChange}
placeholder="$ 0,00"
prefix="$ "
thousandSeparator="."
value={value}
/>
I would like to know this as well
Both outputs you mentioned seems incorrect. It should be $ 12.345.00 as you have mentioned fixedDecimalScale. Also, don't forget to pass the isNumericString prop. If you are passing a numeric string as value.
@s-yadav It depends on which locale you are referring. It is correct when using, for instance, pt-BR.
@felri I've found out how to format the number properly - using a formatter. The trick is to divide value by 100.
export default function currencyFormatter(value) {
if (!Number(value)) return "";
const amount = new Intl.NumberFormat("pt-BR", {
style: "currency",
currency: "BRL"
}).format(value / 100);
return `${amount}`;
}
Then you must use this format into your component:
<NumberFormat {...allOtherRequiredProps} format={currencyFormatter} />
@richardaum That's the trick. Thank you very much!
@richardaum thank you, works great
@richardaum I tried with this approach, but the values object returns float value wrongly.
For example, if I type 12345, the field shows R$ 123,45, but the values object returns {formattedValue: "R$聽123,45", value: "12345", floatValue: 12345}
Did this happen to you?
Yeah. This is expected because the approach is based on a formatter only.
So it will only change how the number is displayed. You must handle the
float number and divide it by 100 before persisting it or whatever you do
with this number.
An alternative could be if a implementation is made to make this feature
native, then we could expect float number also be divide by 100
automatically.
You could also implement your own wrapper to this component and expose a
float number already divided by 100.
@felri I've found out how to format the number properly - using a formatter. The trick is to divide value by 100.
export default function currencyFormatter(value) { if (!Number(value)) return ""; const amount = new Intl.NumberFormat("pt-BR", { style: "currency", currency: "BRL" }).format(value / 100); return `${amount}`; }Then you must use this format into your component:
<NumberFormat {...allOtherRequiredProps} format={currencyFormatter} />
Please number formatter ?
@richardaum Thank you so much! (Valeu demais velho)
To clarify, format only transforms the value in the UI.
To make sure I get the right value in onValueChange I used:
onValueChange={values => {
if(!onValueChange) { return; }
const val = (parseFloat(values.value) / 100).toFixed(2)
const floatVal = values.floatValue && values.floatValue / 100
onValueChange({value: val, floatValue: floatVal, formattedValue, values.formattedValue})
}}
So if I type 900, val === "9.00" and floatVal === 9, while values.value === "900" and values.floatValue === 900.
I also had to fix the initial value
value={String(parseFloat(value + "" ?? "0") * 100)}
+ "" is to coerce number to string, ?? "0" is to default to "0" if value is undefined.
With these changes, internally the value is still 900 but on the consumer side the value is 9.00
Additionally, I had to fix the caret positioning with
onFocus={e => {
if (inputRef.current && value) {
const positionLastDigit = inputRef.current.value.length - suffix.length;
setCaretPosition(inputRef.current, positionLastDigit);
}
props.onFocus && props.onFocus(e);
}}
with setCaretPosition being a rip-off of https://github.com/s-yadav/react-number-format/blob/8af37958c69ff1e0252282d37e922a913e52e046/lib/utils.js#L146
Yeah. This is expected because the approach is based on a formatter only. So it will only change how the number is displayed. You must handle the float number and divide it by 100 before persisting it or whatever you do with this number. An alternative could be if a implementation is made to make this feature native, then we could expect float number also be divide by 100 automatically. You could also implement your own wrapper to this component and expose a float number already divided by 100.
Thats works perfectly for me, also the other solution. Many thanks.
Also you need to fix setting the value externally and returning the right value as said here:
To clarify,
formatonly transforms the value in the UI.To make sure I get the right value in
onValueChangeI used:onValueChange={values => { if(!onValueChange) { return; } const val = (parseFloat(values.value) / 100).toFixed(2) const floatVal = values.floatValue && values.floatValue / 100 onValueChange({value: val, floatValue: floatVal, formattedValue, values.formattedValue}) }}So if I type 900,
val === "9.00"andfloatVal === 9, whilevalues.value === "900"andvalues.floatValue === 900.I also had to fix the initial value
value={String(parseFloat(value + "" ?? "0") * 100)}
+ ""is to coerce number to string,?? "0"is to default to "0" if value is undefined.With these changes, internally the value is still 900 but on the consumer side the value is 9.00
Additionally, I had to fix the caret positioning with
onFocus={e => { if (inputRef.current && value) { const positionLastDigit = inputRef.current.value.length - suffix.length; setCaretPosition(inputRef.current, positionLastDigit); } props.onFocus && props.onFocus(e); }}with setCaretPosition being a rip-off of
Most helpful comment
@felri I've found out how to format the number properly - using a formatter. The trick is to divide value by 100.
Then you must use this format into your component: