0

I'm trying to create a numbered input with a max length.

However, when I try to type 1.2345, anything after the decimal doesn't get stored. Upon further inspection, target.value never includes the decimal point despite being a string. Why is that?

<script>
let props = defineProps({
  hint: String,
  min: Number,
  max: Number,
  maxLen: Number,

  modelValue: Number,
})
let emits = defineEmits({
  'update:modelValue': (it: number) => true
})

function onInput(event: Event) {
  let target = event.target as HTMLInputElement
  if (!target) return

  console.log(typeof target.value, target.value) // <<< prints string, 1
  target.value = target.value.slice(0, props.maxLen)

  // let value = +target.value
  // let oldValue = value
  // value = Math.min(value, props.max ?? value)
  // value = Math.max(value, props.min ?? value)

  // u.log(oldValue, value)
  // if (oldValue !== value) {
  //   u.log('update', value)
  //   target.value = '' + value
  //   emits('update:modelValue', value)
  // }
}
</script>
<template>
  <input class="form-control
        block
        w-full
        px-3
        py-1.5
        text-base
        font-normal
        text-gray-700
        bg-white disabled:bg-gray-100 
        bg-clip-padding
        border border-solid border-gray-300
        rounded
        transition
        ease-in-out
        m-0
        focus:text-gray-700 focus:bg-white focus:border-blue-600 focus:outline-none
        "
      type="number"
      @input="onInput"
      :placeholder="hint" />
</template>

1 Answer 1

2

target.value never includes the decimal point despite being a string. Why is that?

When using <input type="number"/>, the input's value is converted from a string to a number, and then gets converted to a string again, at which point th decimal is removed. This is why when you enter 1.2 you get 21 (you can also use valueAsNumber which skips making it into a string, but doesn't really solve the problem)

  • type 1 => onInput target.value is 1
  • type . => onInput target.value is still 1 (not 1.)
  • onInput updates the value from 1. to 1 and because of the change, the caret is now at the beginning
  • type 2 => onInput target.value is 21

That's the problem, as to your solution, it depends on your expected behaviour.

you could try something like this to validate whether the value needs to be updated instead of just updating it

const max = 5;
const newVal = target.value.slice(0, max)
if(parseFloat(newVal)+"" !== newVal) {
    target.value = parseFloat(newVal)
}
else if(newVal !== target.value) {
    target.value = parseFloat(newVal)
}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.