skip to Main Content

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

enter image description here

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}
/>

2

Answers


  1. 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 element lendFeeInput.
    • 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.

    CODE DEMO

    Login or Signup to reply.
  2. What about seeing it in a different perspective?

    enter image description here

    You’re trying to put % sign inside the string of numbers.

    I think making one more element for the percent sign and putting it next to each other would do the trick. Use flex to style it then.

    Also, it would be helpful if you want to do something with the number value; for instance, you don’t need to do extra slicing.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search