AppAutoComplete.vue 2.2KB

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