rifm
rifm copied to clipboard
help with currency mask and rifm props
I'm trying to apply this mask 0.000.000,00
for Brazilian currency
I'd like to have the following behavior:
1 cents -> 0,01 (when user types 1, it gets 0,01) 10 cents -> 0,10 100 cents -> 1,00 100000 cents -> 1.000,00
I'm not sure if I need to use format
, replace
, mask true or false
, or append
to achieve this behavior
any thoughts on this?
would it be a stupid suggestion if I said to divide the field entrance by 100? so, if the user types "1", in the text field it would appear "0.01"
I don't know if it's the better solution, but: https://codesandbox.io/s/damp-resonance-xcz6d?file=/src/App.js
The tricky is that format
receive a str value (formatted one, like "R$ 0,01").
You need to get the number from it (regex + parseInt), then back it to string (formatting back to "R$ 0,01").
The cents parts, as @igorlrnc said, is just divide it by 100 with toFixed(2)
it is looking great, tks
the only problem is the delete
keycode that is jumping the cursor to the beginning of the input
is there a way to fix it?
I think you should use accept
prop (not sure). But I couldn't make it work here
R$ 1,23|
press delete
|R$ 0,12
I figured out that it only happens when you delete the last char when it's only three digits (4+ works)
what is the best way to add a failing test case for this behavior?
what about an advanced
prop where the user could return the cursor
position?
this line is breaking the backspace behavior
https://github.com/realadvisor/rifm/blob/master/src/Rifm.js#L211
// Visually improves working with masked values, // like cursor jumping over refused symbols // as an example date mask: was "5|1-24-3" then user pressed "6" // it becomes "56-|12-43" with this code, and "56|-12-43" without
working version without that line
const numberFormat = (str: string) => {
if (str === '') str = '0';
const value = (parseInt(str.replace(/[^\d]+/gi, ''), 10) / 100).toFixed(2);
const getCurrencyFormat = () => {
if (!value) {
return '';
}
return new Intl.NumberFormat('pt-br', {
style: 'currency',
currency: 'BRL',
})
.format(value)
.replace('R$ ', '');
};
return getCurrencyFormat();
};
const rifm = useMask({
value,
onChange: (value) => {
const e = { target: { value } };
onChange(e);
},
format: numberFormat,
});
do you see a bug where the second inserted number after an erase goes to the decimals?
https://user-images.githubusercontent.com/14146176/160015674-e497c02e-c96e-4e53-8c20-da53ec590cd3.mp4
added a new if to the numberFormat above to fix it:
const numberFormat = (str: string) => {
if (str === '') str = '0';
if (str.includes('R$') && !isNaN(parseInt(str.charAt(0)))) {
str = str.replace('R$', '')
str = str.slice(1, str.length) + str.charAt(0)
}
const value = (parseInt(str.replace(/[^\d]+/gi, ''), 10) / 100).toFixed(2);
const getCurrencyFormat = () => {
if (!value) {
return '';
}
return new Intl.NumberFormat('pt-br', {
style: 'currency',
currency: 'BRL',
})
.format(value)
.replace('R$ ', '');
};
return getCurrencyFormat();
};