Search code examples
javascriptajaxvue.jslodashvue-multiselect

Issue in throttling ajax requests using vue-multiselect and lodash


I have a vue app containing a vue-multiselect and I want to load the multiselect options through ajax. I am using lodash.throttle to throttle the firing of ajax requests as the user types in the search criteria. But whatever I do, I am seeing multiple requests being fired for each character I type in search. What I am doing wrong? Thanks in advance.

<template>
<multiselect :options="allLocations.map(p => p.externalId)" 
                :searchable="true" 
                :custom-label="uuid => {const sel = allLocations.filter(s => s.externalId === uuid); return sel.length === 1 ? sel[0].name + ' (' + sel[0].type + ')' : '';}" 
                class="mx-1 my-1" 
                style="width:500px;" 
                v-model="locations"
                :clear-on-select="true" 
                :close-on-select="false" 
                :show-labels="true" 
                placeholder="Pick Locations to filter" 
                :multiple="true" 
                :loading="locationsLoading" 
                :internal-search="false"
                @search-change="findLocations"
                @input="updateLocations" 
                :allowEmpty="true" />
</template>
<script>
import {throttle} from 'lodash'
export default {
name: 'test-throttle-component',
data() {
allLocations: [],
locationsLoading: false,
locations: [],
},
methods: {
findLocations(search) {
      this.$log.debug("Going to find locations for search criteria", search)
      const params = {search: search}
      this.locationsLoading = true
      const self = this
      throttle(() => self.$http.get("locations/ddlist", {params}).then(res => {
        self.allLocations = res.data.items
        self.locationsLoading = false
      }), 5000)()
    },
updateLocations() {
      const self = this
      this.$store.dispatch('updateSelectedLocations', this.locations)
        .then(() => self.emitRefresh())
    },
}
}
</script>

Solution

  • @strelok2010 is nearly right but I think he overlooked the fact that the vue multiselect @search-change handler expects a handler that takes the search argument and so the code won't work as is. Also I think, this won't resolve to the component inside the arrow function and so you may have to use standard JS function. Here is what I think would work.

    findLocations: throttle(function(search) {
          this.$log.debug("Going to find locations for search criteria", search)
          const params = {search: search}
          const self = this
          this.locationsLoading = true
          self.$http.get("locations/ddlist", {params}).then(res => {
            self.allLocations = res.data.items
            self.locationsLoading = false
          }
    }, 5000)