Based on Is there specific number input component in Vuetify? I'm trying to create a numeric input.
The input and output value is unknown
so it could be undefined
or null
because one might want to clear the field so it should not respond with 0
.
The input component should not have "up"/"down" buttons if possible.
If the user passes in a flag isAcceptingFloatingPointNumbers = false
this input should only accept integer values ( it should not be possible to type floats )
<template>
<v-app>
<v-main>
<v-text-field
type="number"
label="number input"
:clearable="true"
:model-value="num"
@update:modelValue="num = $event"
/>
</v-main>
</v-app>
</template>
<script setup lang="ts">
import { ref, watch, Ref } from 'vue'
const num: Ref<unknown> = ref(undefined)
watch(num, () => console.log(num.value))
</script>
How can I make sure the user can only type integer values if the flag isAcceptingFloatingPointNumbers
returns false
? The only thing coming to my mind is to append a custom rule like
v => Number.isInteger(v) || 'Must be integer'
but AFAIK this rule would trigger even if the value could be undefined
. Is there a way to prevent the user input instead?
Based on yoduh's answer I tried this ( reproduction link )
NumberField.vue
<template>
<v-text-field
type="number"
label="number input"
:clearable="true"
:model-value="num"
@update:modelValue="emit('update:modelValue', $event)"
@keypress="filterInput"
/>
</template>
<script setup lang="ts">
const props = defineProps<{
num: unknown;
isAcceptingFloatingPointNumbers: boolean;
}>();
const emit = defineEmits<{
(e: "update:modelValue", newValue: unknown): void;
}>();
function filterInput(inputEvent) {
if(props.isAcceptingFloatingPointNumbers.value) {
return true;
}
const inputAsString = inputEvent.target.value.toString() + inputEvent.key.toString();
const inputValue = Number(inputAsString);
if(!Number.isInteger(inputValue)) {
inputEvent.preventDefault();
}
return true;
}
</script>
I'm consuming the component like so
<template>
<number-field :num="num" :isAcceptingFloatingPointNumbers="false" @update:model-value="num = $event" />
</template>
<script setup lang="ts">
import { ref, watch } from 'vue'
import NumberField from "./NumberField.vue";
const num: Ref<unknown> = ref(undefined);
watch(num, () => console.log(num.value));
</script>
The problem is that my filter function is wrong. It's still possible to type "12.4" because the filter ignores "12." and then converts "12.4" to 124.
Does someone got any ideas how to fix this?