Number.vue 1.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. <!--
  2. An input for numeric values
  3. -->
  4. <template>
  5. <v-text-field
  6. ref="input"
  7. :modelValue.number="modelValue"
  8. hide-details
  9. single-line
  10. :density="density"
  11. type="number"
  12. @update:modelValue="modelValue = keepInRange(cast($event)); emitUpdate()"
  13. />
  14. </template>
  15. <script setup lang="ts">
  16. import {PropType} from "@vue/runtime-core";
  17. type Density = null | 'default' | 'comfortable' | 'compact';
  18. const props = defineProps({
  19. modelValue: {
  20. type: Number,
  21. required: true
  22. },
  23. default: {
  24. type: Number,
  25. required: false,
  26. default: 0
  27. },
  28. min: {
  29. type: Number,
  30. required: false,
  31. default: null
  32. },
  33. max: {
  34. type: Number,
  35. required: false,
  36. default: null
  37. },
  38. density: {
  39. type: String as PropType<Density>,
  40. required: false,
  41. default: 'default'
  42. }
  43. })
  44. /**
  45. * Reference to the v-text-field
  46. */
  47. const input: Ref<any> = ref(null)
  48. /**
  49. * Cast the value to a number, or fallback on default value
  50. * @param val
  51. */
  52. const cast = (val: number | string): number => {
  53. val = Number(val)
  54. if (isNaN(val)) {
  55. return props.default
  56. }
  57. return val
  58. }
  59. /**
  60. * Ensure the value is between min and max values
  61. * @param val
  62. */
  63. const keepInRange = (val: number) => {
  64. if (props.min !== null && props.max !== null && props.min >= props.max) {
  65. console.warn('Number input: minimum value is greater than maximum value')
  66. }
  67. if (props.min !== null && val < props.min) {
  68. val = props.min
  69. }
  70. if (props.max !== null && val > props.max) {
  71. val = props.max
  72. }
  73. return val
  74. }
  75. const emit = defineEmits(['update:modelValue'])
  76. /**
  77. * Emit the update event
  78. */
  79. const emitUpdate = () => {
  80. emit('update:modelValue', props.modelValue)
  81. }
  82. /**
  83. * Setup min and max values at the input level
  84. */
  85. onMounted(() => {
  86. const inputElement = input.value.$el.querySelector('input')
  87. if (props.min !== null) {
  88. inputElement.min = props.min
  89. }
  90. if (props.max !== null) {
  91. inputElement.max = props.max
  92. }
  93. })
  94. </script>