AutocompleteWithAPI.vue 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. <!--
  2. Liste déroulante avec autocompletion (les données sont issues
  3. de l'api Opentalent)
  4. @see https://vuetifyjs.com/en/components/autocompletes/#usage
  5. -->
  6. <template>
  7. <main>
  8. <v-autocomplete
  9. v-model="model"
  10. :value="data"
  11. :items="items"
  12. :loading="isLoading"
  13. :search-input.sync="search"
  14. hide-no-data
  15. hide-selected
  16. item-text="textDisplay"
  17. :item-value="itemValue"
  18. :label="$t(label_field)"
  19. :placeholder="$t('start_your_research')"
  20. prepend-icon="mdi-magnify"
  21. :return-object="returnObject"
  22. />
  23. </main>
  24. </template>
  25. <script lang="ts">
  26. import { defineComponent, computed, watch, ref, useContext, onUnmounted, Ref } from '@nuxtjs/composition-api'
  27. import * as _ from 'lodash'
  28. import { QUERY_TYPE } from '~/types/enums'
  29. export default defineComponent({
  30. props: {
  31. label: {
  32. type: String,
  33. required: false,
  34. default: null
  35. },
  36. field: {
  37. type: String,
  38. required: false,
  39. default: null
  40. },
  41. data: {
  42. type: String,
  43. required: false,
  44. default: null
  45. },
  46. readonly: {
  47. type: Boolean,
  48. required: false
  49. },
  50. itemValue: {
  51. type: String,
  52. default: 'id'
  53. },
  54. itemText: {
  55. type: Array,
  56. required: true
  57. },
  58. returnObject: {
  59. type: Boolean,
  60. default: false
  61. }
  62. },
  63. setup (props) {
  64. const { $dataProvider } = useContext()
  65. const search:Ref<string|null> = ref(null)
  66. const model = ref(null)
  67. const count = ref(0)
  68. const entries = ref([])
  69. const isLoading = ref(false)
  70. const items = computed(() => {
  71. return entries.value.map((entry) => {
  72. const textDisplay:Array<string> = []
  73. for (const text of props.itemText) {
  74. textDisplay.push(entry[text as string])
  75. }
  76. return Object.assign({}, entry, { textDisplay: textDisplay.join(' ') })
  77. })
  78. })
  79. const unwatch = watch(search, _.debounce(async (research) => {
  80. // Items have already been requested
  81. if (isLoading.value) { return }
  82. isLoading.value = true
  83. const response = await $dataProvider.invoke({
  84. type: QUERY_TYPE.DEFAULT,
  85. url: `gps-coordinate-searching?city=${research}`
  86. })
  87. count.value = response.length
  88. entries.value = response
  89. isLoading.value = false
  90. }, 500))
  91. onUnmounted(() => {
  92. unwatch()
  93. })
  94. return {
  95. label_field: props.label ?? props.field,
  96. count,
  97. isLoading,
  98. items,
  99. search,
  100. model
  101. }
  102. }
  103. })
  104. </script>
  105. <style scoped>
  106. </style>