AppInputNumber.vue 2.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. <script setup>
  2. import { computed } from 'vue'
  3. const props = defineProps({
  4. label: {
  5. type: String,
  6. required: true,
  7. },
  8. disabled: {
  9. type: Boolean,
  10. default: false,
  11. },
  12. type: {
  13. type: String,
  14. default: 'text',
  15. },
  16. mode: {
  17. type: String,
  18. default: 'decimal',
  19. },
  20. incrementButtonClass: {
  21. type: String,
  22. default: null,
  23. },
  24. decrementButtonClass: {
  25. type: String,
  26. default: null,
  27. },
  28. incrementButtonIcon: {
  29. type: String,
  30. default: 'pi pi-angle-up',
  31. },
  32. decrementButtonIcon: {
  33. type: String,
  34. default: 'pi pi-angle-down',
  35. },
  36. showButtons: {
  37. type: Boolean,
  38. default: false,
  39. },
  40. buttonLayout: {
  41. type: String,
  42. default: 'stacked',
  43. },
  44. min: {
  45. type: Number,
  46. default: null,
  47. },
  48. max: {
  49. type: Number,
  50. default: null,
  51. },
  52. step: {
  53. type: Number,
  54. default: 1,
  55. },
  56. prefix: {
  57. type: String,
  58. default: null,
  59. },
  60. suffix: {
  61. type: String,
  62. default: null,
  63. },
  64. placeholder: {
  65. type: String,
  66. required: true,
  67. },
  68. useGrouping: {
  69. type: Boolean,
  70. default: true,
  71. },
  72. currency: {
  73. type: String,
  74. default: undefined,
  75. },
  76. locale: {
  77. type: String,
  78. default: undefined,
  79. },
  80. error: {
  81. type: String,
  82. default: null,
  83. },
  84. currencyDisplay: {
  85. type: String,
  86. default: undefined,
  87. },
  88. modelValue: null,
  89. })
  90. defineEmits(['update:modelValue'])
  91. const isError = computed(() => (props.error ? true : false))
  92. const forLabel = computed(() => props.label.toLowerCase().replace(/\s+/g, '-'))
  93. const ariaDescribedbyLabel = computed(() => props.label.toLowerCase().replace(/\s+/g, '-') + '-help')
  94. </script>
  95. <template>
  96. <div class="field">
  97. <label :for="forLabel">{{ label }}</label>
  98. <InputNumber
  99. class="w-full"
  100. input-class="w-full"
  101. :currency="currency"
  102. :currency-display="currencyDisplay"
  103. :locale="locale"
  104. :class="{ 'p-invalid': isError }"
  105. :id="forLabel"
  106. :aria-describedby="ariaDescribedbyLabel"
  107. :type="type"
  108. :placeholder="placeholder"
  109. :model-value="modelValue"
  110. :disabled="disabled"
  111. :prefix="prefix"
  112. :suffix="suffix"
  113. :step="step"
  114. :min="min"
  115. :max="max"
  116. :mode="mode"
  117. :use-grouping="useGrouping"
  118. :show-buttons="showButtons"
  119. :button-layout="buttonLayout"
  120. :increment-button-class="incrementButtonClass"
  121. :decrement-button-class="decrementButtonClass"
  122. :increment-button-icon="incrementButtonIcon"
  123. :decrement-button-icon="decrementButtonIcon"
  124. @input="$emit('update:modelValue', $event.value)"
  125. />
  126. <small v-if="error" :id="ariaDescribedbyLabel" :class="{ 'p-error': isError }">
  127. {{ error }}
  128. </small>
  129. </div>
  130. </template>