AutocompleteWithAPI.vue 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  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. },
  35. field: {
  36. type: String,
  37. required: false
  38. },
  39. data: {
  40. type: String,
  41. required: false
  42. },
  43. readOnly: {
  44. type: Boolean,
  45. required: false
  46. },
  47. itemValue: {
  48. type: String,
  49. default: 'id'
  50. },
  51. itemText: {
  52. type: Array,
  53. required: true
  54. },
  55. returnObject: {
  56. type: Boolean,
  57. default: false
  58. }
  59. },
  60. setup (props) {
  61. const { $dataProvider } = useContext()
  62. const search:Ref<string|null> = ref(null)
  63. const model = ref(null)
  64. const count = ref(0)
  65. const entries = ref([])
  66. const isLoading = ref(false)
  67. const items = computed(() => {
  68. return entries.value.map((entry) => {
  69. const textDisplay:Array<string> = []
  70. for (const text of props.itemText) {
  71. textDisplay.push(entry[text as string])
  72. }
  73. return Object.assign({}, entry, { textDisplay: textDisplay.join(' ') })
  74. })
  75. })
  76. const unwatch = watch(search, _.debounce(async (research) => {
  77. // Items have already been requested
  78. if (isLoading.value) { return }
  79. isLoading.value = true
  80. const response = await $dataProvider.invoke({
  81. type: QUERY_TYPE.DEFAULT,
  82. url: `gps-coordinate-searching?city=${research}`
  83. })
  84. count.value = response.length
  85. entries.value = response
  86. isLoading.value = false
  87. }, 500))
  88. onUnmounted(() => {
  89. unwatch()
  90. })
  91. return {
  92. label_field: props.label ?? props.field,
  93. count,
  94. isLoading,
  95. items,
  96. search,
  97. model
  98. }
  99. }
  100. })
  101. </script>
  102. <style scoped>
  103. </style>