AppAutocompleteBasic.vue 2.2KB

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