Problem:
I made an input that show percentage like 1.1% (and not accepting 00 at the beginning) when typing but the cursor goes to the end while typing.
is there a away to keep it before % symbol
function formatPercent(amount) {
return amount + '%'
}
const [lendData, setLendData] = useState({
lendValue: '',
lendFee: '',
})
function handleChange(e) {
let { name, value } = e.target
if (name == 'lendValue') {
// prevent first character if it 0 and removing separator
value = value.replace(/^0+|[^0-9]/g, '')
setLendData((prev) => {
return {
...prev,
[name]: value,
}
})
} else if (name == 'lendFee') {
// prevent first character if it 0
value = value.replace(/^0+|[^0-9,.]/g, '')
console.log(value)
setLendData((prev) => {
return {
...prev,
[name]: value,
}
})
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<input
type='text'
inputMode='decimal'
name='lendFee'
id='lendFee'
placeholder='0%'
value={
lendData.lendFee ? formatPercent(lendData.lendFee) : ''
}
onChange={handleChange}
/>
Solution:
You can try the below code:
function formatPercent(amount) {
return amount + '%';
}
function App() {
const [lendData, setLendData] = useState({
lendValue: '',
lendFee: '',
});
const lendFeeInput = useRef(null);
function handleChange(e) {
let { name, value } = e.target;
if (name === 'lendValue') {
// prevent first character if it 0 and removing separator
value = value.replace(/^0+|[^0-9]/g, '');
setLendData((prev) => {
return {
...prev,
[name]: value,
};
});
} else if (name === 'lendFee') {
const cursorPosition = e.target.selectionStart;
// prevent first character if it 0
value = value.replace(/^0+|[^0-9,.]/g, '');
setLendData((prev) => {
return {
...prev,
[name]: value,
};
});
// Restoring cursor position
setTimeout(() => {
lendFeeInput.current.selectionStart = cursorPosition;
lendFeeInput.current.selectionEnd = cursorPosition;
}, 0);
}
}
Explanation of the code changes:
- I have used
useRef
hook and created a ref for the input elementlendFeeInput
. - I stored the current cursor position before updating the input value:
const cursorPosition = e.target.selectionStart;
- Finally I have restored the cursor position after updating the input value using
setTimeout
to ensure the input value has been updated.