Skip to content
Snippets Groups Projects
Autocomplete.vue 3.1 KiB
Newer Older
<template>
  <v-autocomplete
      v-model="select"
      :loading="loading"
      :items="items"
      :search-input.sync="search"
      item-text="label"
      :menu-props="{maxHeight: 500, transition: 'fade-transition'}"
      append-icon="search"
      return-object
      hide-no-data
      hide-details
      label="Søk..."
      solo
      auto-select-first
      placeholder="Søk..."
      ref="autocomplete"
      color="rgb(188, 71, 123)"
      dense
    >
    <template v-slot:item="data">
    <span class="search-hit">{{data.item.label}} </span> ({{data.item.lang_set ? Array.from(data.item.lang_set).sort().join(', ') : 'fritekstsøk'}})
    </template>
  </v-autocomplete>
</template>

<script>
  import axios from "axios"
  import debounce from "debounce"

  export default {
    props: {
      endpoint: String
    },
    data: function() {
      return {
        loading: false,
        items: [],
        search: null,
        select: null,
        debounced: debounce(function(q, self) {
          self.loading = true
          return axios.get(self.endpoint + 'suggest?q=' + encodeURIComponent(q))
                      .then(
                            function(response) {
                                let hits = []
                                if (q == self.search) {
                                  response.data.forEach((item, i) => {
                                    let match = encodeURIComponent(item.match)

                                    if (! hits[0] || hits[0].word != match) {
                                      hits.splice(0, 0, {q: encodeURIComponent(q), lang_set: new Set(), word: match, articles: []})
                                    }
                                    hits[0].lang_set.add(item.dictionary == 'bob' ? 'bm' : 'nn')
                                    hits[0].articles.push(item)
                                  });
                                  hits.forEach(function (hit) {
                                    if (hit.lang_set) {
                                      hit.label = decodeURIComponent(hit.word)
                                    }
                                  });
                                  hits.reverse()
                                  hits = hits.slice(0, 9)
                                  if (q) {
                                    hits.push({q: encodeURIComponent(q), label: q + ' '})
                                  }
                                }
                                self.items = hits
                                self.loading = false
                              })
      }
    },
    watch: {
      search (val) {
        if (! val) {
          this.items = []
        } else {
          this.run_query(val)
        }
      },
      select(item) {
        this.$emit('submit', item)
Ole Voldsæter's avatar
Ole Voldsæter committed
        let self = this
        setTimeout(() => self.$refs.autocomplete.$refs.input.select(), 1)
      }
    },
    methods: {
      run_query(q) {
        this.debounced(q, this)
  }
</script>
<style scoped>
  .search-hit {
    font-weight: bold;
    margin-right: 5px;
  }
</style>