Open iloveip opened 4 years ago
up
up
up
up
up
up
I'm also interested in this.
@sanniassin can we get an answer?
Also need that
I have an alternative using react hooks. I'll share it with you...
// some code here
const [budget, setBudget] = useState(null) //any number
const [format, setFormat] = useState('9') //initial format
useEffect(() => {
if (budget) {
const num = budget.toString()
const len = num.length
const arr = []
for (let i = 0; i < len; i++) {
arr.push('9');
if ((i + 1) % 3 == 0 && i !== len - 1) {
arr.push('.'); //this can be change with any separator (. or ,)
}
}
const newFormat = arr.reverse().join('');
setFormat(`$ ${newFormat}`);
}
}, [budget]);
return(
//some code here
<InputMask
mask={format}
maskChar={null}
value={budget}
onChange={handleInputChange}
onBlur={handleBlur}
inputProps={{
step: 50000,
min: minBudget,
max: maxBudget,
type: 'number',
'aria-labelledby': 'input-slider',
}}
>
{() => <Input className={classes.input} disableUnderline />}
</InputMask>
)
Any update on this one?
With the 3.0.0 alpha version (yarn add react-input-mask@next) you can use the new property beforeMaskedStateChange to write a custom format function:
/**
* Format to Brazilian currency
*/
export const maskToCurrency = ({ nextState }) => {
const { value } = nextState || {}
let amountFormatted = value?.replace?.(/\D/g, '')
amountFormatted = amountFormatted?.replace?.(/^0+/g, '')
if (amountFormatted?.length === 2) {
return {
...nextState,
value: `R$ ${amountFormatted}`,
selection: {
start: amountFormatted.length + 3,
end: amountFormatted.length + 3
}
}
}
const amountFormattedWithComma = amountFormatted?.replace?.(
/(?=\d{2})(\d{2})$/,
',$1'
)
const amountFormattedWithDot = amountFormattedWithComma?.replace?.(
/(\d)(?=(\d{3})+(?!\d))/g,
'$1.'
)
if (amountFormattedWithDot) {
return {
...nextState,
value: `R$ ${amountFormattedWithDot}`,
selection: {
start: amountFormattedWithDot.length + 3,
end: amountFormattedWithDot.length + 3
}
}
}
return nextState
}
And in your React component:
<InputMask
mask="R$ 9999999999" // Don't use dots and commas
alwaysShowMask={false}
beforeMaskedStateChange={maskToCurrency}
value={value}
onChange={(e) => setValue(e.target.value)}
>
<YourInputComponent type="text" name="amount" {...otherProps} />
</InputMask>
Example of the masked value: R$ 12.345,67
<InputMask mask="R$ 9999999999" // Don't use dots and commas alwaysShowMask={false} beforeMaskedStateChange={maskToCurrency} value={value} onChange={(e) => setValue(e.target.value)} > <YourInputComponent type="text" name="amount" {...otherProps} /> </InputMask>
Hi @alexandrehpiva it is not working or maybe I am missing something, could you provide a working example on codesandbox please? thank you 🙂
In case it's of use to anyone, I had to implement number formatting (not currency, the currency symbol is shown outside the input) so I made a reusable hook
export const useFormattedIntegerMask = ({
maxDigits,
}: {
maxDigits: number;
}): { mask: Mask; unformat: (string) => number } => {
let highestNum = 1;
new Array(maxDigits).fill(0).forEach(() => (highestNum = highestNum * 10));
const maskLength = new Intl.NumberFormat().format(highestNum).length - 1;
const mask = new Array(maskLength).fill("9").join("");
const separator = new Intl.NumberFormat().formatToParts(1000)[1].value;
return {
unformat: (str) => {
return parseInt(str.replaceAll(separator, ""));
},
mask: {
mask,
maskPlaceholder: "",
beforeMaskedStateChange: ({ previousState, currentState, nextState }) => {
const newValue = nextState.value.length
? new Intl.NumberFormat().format(parseInt(nextState.value))
: nextState.value;
const extraCharCount =
Number.isInteger(previousState?.selection?.start) &&
newValue.length > 3 &&
currentState.selection.start < previousState.selection.start
? currentState.selection.start - previousState.selection.start
: newValue.slice(0, currentState.selection.start).split(separator).length - 1;
return {
...nextState,
value: newValue,
selection: {
start: nextState.selection.start + extraCharCount,
end: nextState.selection.end + extraCharCount,
},
};
},
},
};
};
Note that this assumes no decimal points as our input is for integers only
Hi there,
Is there anyway to use this library for currency formating? For example, if I need to allow unknown length of digits before decimal point and only one or two digits after the decimal point?
There was a similar issue #44, but it has been closed.