AppDropdown.vue 2.3KB

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