AppAutoComplete.vue 2.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  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. class="w-full"
  62. inputClass="w-full"
  63. :model-value="modelValue"
  64. :id="forLabel"
  65. :class="{ 'p-invalid': isError }"
  66. :field="field"
  67. :placeholder="placeholder"
  68. :suggestions="suggestions"
  69. :auto-highlight="true"
  70. :disabled="disabled"
  71. @input="$emit('update:modelValue', $event.target.value)"
  72. @item-select="onSelect"
  73. @complete="onComplete"
  74. >
  75. <template #item="slotProps">
  76. <slot name="item" :item="slotProps.item" />
  77. </template>
  78. </AutoComplete>
  79. <div class="flex flex-column">
  80. <small
  81. v-if="error"
  82. class="mt-1"
  83. :class="{
  84. 'mb-2': empty,
  85. 'p-error': isError,
  86. }"
  87. :id="ariaDescribedbyLabel"
  88. >
  89. {{ error }}
  90. </small>
  91. <small v-if="empty" class="mt-1">
  92. <slot name="empty" />
  93. </small>
  94. </div>
  95. </div>
  96. </template>