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();
};