AppDropdown.vue 1.6KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970
  1. <script setup>
  2. import { computed } from 'vue'
  3. const props = defineProps({
  4. label: {
  5. type: String,
  6. default: '',
  7. },
  8. optionLabel: {
  9. type: String,
  10. default: 'label',
  11. },
  12. optionValue: {
  13. type: String,
  14. default: 'value',
  15. },
  16. placeholder: String,
  17. options: {
  18. type: Array,
  19. required: true,
  20. },
  21. error: String,
  22. modelValue: [String, Number, Boolean, Array, Object],
  23. })
  24. defineEmits(['update:modelValue'])
  25. const isError = computed(() => (props.error ? true : false))
  26. const forLabel = computed(() => props.label.toLowerCase().replace(/\s+/g, '-'))
  27. const ariaDescribedbyLabel = computed(() => props.label.toLowerCase().replace(/\s+/g, '-') + '-help')
  28. const selectedDropdownLabel = (value) => {
  29. const result = props.options.find((option) => option[props.optionValue] == value)
  30. if (result) {
  31. return result[props.optionLabel]
  32. }
  33. }
  34. </script>
  35. <template>
  36. <label :for="forLabel">{{ label }}</label>
  37. <Dropdown
  38. class="w-full"
  39. :class="{ 'p-invalid': isError }"
  40. :id="forLabel"
  41. :aria-describedby="ariaDescribedbyLabel"
  42. :option-label="optionLabel"
  43. :option-value="optionValue"
  44. :placeholder="placeholder"
  45. :options="options"
  46. :model-value="modelValue"
  47. @change="$emit('update:modelValue', $event.value)"
  48. >
  49. <template #value="slotProps">
  50. <div v-if="slotProps.value">
  51. {{ selectedDropdownLabel(slotProps.value) }}
  52. </div>
  53. <div v-else>
  54. {{ slotProps.placeholder }}
  55. </div>
  56. </template>
  57. </Dropdown>
  58. <small :id="ariaDescribedbyLabel" :class="{ 'p-error': isError }">
  59. {{ error }}
  60. </small>
  61. </template>