AppAutoComplete.vue 2.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. <script setup>
  2. import { computed } from 'vue'
  3. import { Inertia } from '@inertiajs/inertia'
  4. const props = defineProps({
  5. label: {
  6. type: String,
  7. required: true,
  8. },
  9. disabled: {
  10. type: Boolean,
  11. default: false,
  12. },
  13. placeholder: {
  14. type: String,
  15. required: true,
  16. },
  17. error: {
  18. type: String,
  19. default: null,
  20. },
  21. field: {
  22. type: String,
  23. required: true,
  24. },
  25. empty: {
  26. type: Boolean,
  27. default: false,
  28. },
  29. refreshData: {
  30. type: String,
  31. required: true,
  32. },
  33. suggestions: {
  34. type: Array,
  35. required: true,
  36. },
  37. modelValue: null,
  38. })
  39. const emit = defineEmits(['update:modelValue'])
  40. const isError = computed(() => (props.error ? true : false))
  41. const forLabel = computed(() => props.label.toLowerCase().replace(/\s+/g, '-'))
  42. const ariaDescribedbyLabel = computed(
  43. () => props.label.toLowerCase().replace(/\s+/g, '-') + '-error'
  44. )
  45. const onComplete = (event) => {
  46. Inertia.reload({
  47. data: {
  48. [props.refreshData.slice(0, -1)]: event.query,
  49. },
  50. only: [props.refreshData],
  51. })
  52. }
  53. const onSelect = (event) => {
  54. emit('update:modelValue', event.value)
  55. }
  56. </script>
  57. <template>
  58. <div class="field">
  59. <label :for="forLabel">{{ label }}</label>
  60. <AutoComplete
  61. forceSelection
  62. class="w-full"
  63. inputClass="w-full"
  64. :model-value="modelValue"
  65. :id="forLabel"
  66. :class="{ 'p-invalid': isError }"
  67. :field="field"
  68. :placeholder="placeholder"
  69. :suggestions="suggestions"
  70. :auto-highlight="true"
  71. :disabled="disabled"
  72. @input="$emit('update:modelValue', $event.target.value)"
  73. @item-select="onSelect"
  74. @complete="onComplete"
  75. >
  76. <template #item="slotProps">
  77. <slot name="item" :item="slotProps.item" />
  78. </template>
  79. </AutoComplete>
  80. <div class="flex flex-column">
  81. <small
  82. v-if="error"
  83. class="mt-1"
  84. :class="{
  85. 'mb-2': empty,
  86. 'p-error': isError,
  87. }"
  88. :id="ariaDescribedbyLabel"
  89. >
  90. {{ error }}
  91. </small>
  92. <small v-if="empty" class="mt-1">
  93. <slot name="empty" />
  94. </small>
  95. </div>
  96. </div>
  97. </template>