AppDropdown.vue 2.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  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. placeholder: {
  13. type: String,
  14. required: true,
  15. },
  16. error: {
  17. type: String,
  18. default: null,
  19. },
  20. optionLabel: {
  21. type: String,
  22. default: 'label',
  23. },
  24. optionValue: {
  25. type: String,
  26. default: 'value',
  27. },
  28. optionDisabled: {
  29. type: String,
  30. default: 'disabled',
  31. },
  32. optionGroupChildren: {
  33. type: String,
  34. default: null,
  35. },
  36. optionGroupLabel: {
  37. type: String,
  38. default: null,
  39. },
  40. options: {
  41. type: Array,
  42. required: true,
  43. },
  44. modelValue: null,
  45. })
  46. defineEmits(['update:modelValue'])
  47. const isError = computed(() => (props.error ? true : false))
  48. const forLabel = computed(() =>
  49. props.label ? props.label.toLowerCase().replace(/\s+/g, '-') : null
  50. )
  51. const ariaDescribedbyLabel = computed(() =>
  52. props.label ? props.label.toLowerCase().replace(/\s+/g, '-') + '-help' : null
  53. )
  54. const selectedDropdownLabel = (value) => {
  55. const result = props.options.find(
  56. (option) => option[props.optionValue] == value
  57. )
  58. if (result) {
  59. return result[props.optionLabel]
  60. }
  61. }
  62. </script>
  63. <template>
  64. <div class="field">
  65. <label v-if="label" :for="forLabel">{{ label }}</label>
  66. <Dropdown
  67. class="w-full"
  68. :class="{ 'p-invalid': isError }"
  69. :id="forLabel"
  70. :aria-describedby="ariaDescribedbyLabel"
  71. :option-disabled="optionDisabled"
  72. :option-group-children="optionGroupChildren"
  73. :option-group-label="optionGroupLabel"
  74. :option-label="optionLabel"
  75. :option-value="optionValue"
  76. :placeholder="placeholder"
  77. :options="options"
  78. :model-value="modelValue"
  79. :disabled="disabled"
  80. @change="$emit('update:modelValue', $event.value)"
  81. >
  82. <template #value="slotProps">
  83. <div v-if="slotProps.value">
  84. {{ selectedDropdownLabel(slotProps.value) }}
  85. </div>
  86. <div v-else>
  87. {{ slotProps.placeholder }}
  88. </div>
  89. </template>
  90. <template #option="{ option, index }">
  91. <slot name="option" :option="option" :index="index" />
  92. </template>
  93. </Dropdown>
  94. <small
  95. v-if="error"
  96. :id="ariaDescribedbyLabel"
  97. :class="{ 'p-error': isError }"
  98. >
  99. {{ error }}
  100. </small>
  101. </div>
  102. </template>