Closed hoanghadu closed 10 months ago
You can use the UInput
component and set the type to number
and use all the other props, it will work.
The increase/decrease buttons of <UInput type="number" />
is tiny, and they are not possible to click in mobile screen.
I also tried to make a component for number input with props and emit, but it it not beautiful as other components of Nuxt UI.
If you want a custom component like in your reference, you can use the ButtonGroup
and put a button with a -
icon, an input with the .number
modifier and another button with the +
icon.
I wrote a custom NumberInput component with increase/decrease buttons for Nuxt UI.
Here is the code, someone might need it.
<template>
<UButtonGroup :size="props.size" orientation="horizontal">
<UButton @click="decrement" icon="i-heroicons-minus-20-solid" color="gray" :disabled="props.min == value"/>
<input type="number"
:value="value"
@input="handleInput"
:min="min"
:max="max"
:step="step"
class="w-20 text-center item-center border-solid border-2 border-gray-300"
/>
<UButton @click="increment" icon="i-heroicons-plus-20-solid" color="gray" :disabled="props.max == value"/>
</UButtonGroup>
</template>
<script setup lang="ts">
import { ref, watch } from 'vue';
// Define props
const props = defineProps({
modelValue: {
type: Number,
default: 0
},
min: {
type: Number,
default: -Infinity
},
max: {
type: Number,
default: Infinity
},
step: {
type: Number,
default: 1
},
size: {
type: String as PropType<"md" | "sm" | "xs" | "2xs" | "lg" | "xl" | undefined>,
default: 'md'
}
});
// Reactive value reference
const value = ref(props.modelValue);
// Watch for external modelValue changes
watch(() => props.modelValue, (newVal) => {
value.value = newVal;
});
// Emit function
const emit = defineEmits(['update:modelValue']);
// Increment function
const increment = () => {
const newValue = Math.min(value.value + props.step, props.max);
value.value = newValue;
emit('update:modelValue', newValue);
};
// Decrement function
const decrement = () => {
const newValue = Math.max(value.value - props.step, props.min);
value.value = newValue;
emit('update:modelValue', newValue);
};
// Handle input change
const handleInput = (event: Event) => {
const target = event.target as HTMLInputElement;
let newValue = parseFloat(target.value);
newValue = Math.max(Math.min(newValue, props.max), props.min);
value.value = newValue;
emit('update:modelValue', newValue);
};
</script>
<style scoped>
/* Hide Arrows From Input Number */
/* Chrome, Safari, Edge, Opera */
input::-webkit-outer-spin-button,
input::-webkit-inner-spin-button {
-webkit-appearance: none;
margin: 0;
}
/* Firefox */
input[type=number] {
-moz-appearance: textfield;
}
</style>
I am still a junior developer, if you find fine any part of the code that could be improved, feel free to comment. Cheers,
The code above has a bug. The prop "size" does not work.
For instance, if we call <NumberInput v-model="val" :size="xs" />
, the console will show a warning: Vue warn]: Property "xs" was accessed during render but is not defined on instance.
Description
It would be great if there is a number input with buttons to increase and decrease value.
Props would be: min, max, step, autofocus, disabled, etc
for reference: https://github.com/marcocesarato/react-native-input-spinner
Additional context
No response