1

I have a text-field (taken from vuetify library) which is used to filter some table in my application.

<v-text-field
  style="min-width: 300px;"
  v-model="filterString"
  label="Search" />

The working principle is simple - every time when the user provides new filter value, the table content should be updated. There is no submit-button or anything like that. Filtering is implemented on the backend-side, so every update demands sending a request to my API. I use a Vue.js watcher to send a request, when the filter string is updated.

watch: {
  async filterString() {
    // some logic containing communication with my api
  },
},

Let's suppose the user of my application types some 10 letters string in search box. Then, my application sends 10 requests to my API, ignoring the fact that first nine of them are useless. And that's my problem. Should i use the clock, and send a request only if a certain amount of time elapses? Is there some event which is fired when the user finishes typing, that i need to subscribe? How to send a request only when the user finishes typing in my box? Thanks for any answer.

Bulchsu
  • 580
  • 11
  • 33
  • take a look at `debounce` package in npm – noobHere Aug 04 '20 at 14:39
  • 1
    The solution would be the use of a classical debounce() functionality. Have a look at https://stackoverflow.com/questions/42199956/how-to-implement-debounce-in-vue2. – RWAM Aug 04 '20 at 14:39

2 Answers2

0

You can still use the @change Vuetify event in combination with a debouncing tool. That would prevent you from performing multiple "useless" requests as you said.

You can either:

Gaetan C.
  • 1,742
  • 13
  • 21
0

What you are looking for is called debouncing. And it is just a timer that waits for you to stop pressing keys.

Here is a quick way to do it using lodash debounce

template:

    <input
            :value="input"
            @change="evt=>textChange(evt.target.value)"
            @input="evt=>textEntry(evt.target.value)"               
    />

javascript:

Imports:

 import { debounce } from 'lodash'

Definition:

 model: {
    prop: 'input',
    event: 'input'
  },
 props: {
    input: {
      default: '',
      type: String
    },
    debounce: {
      default: -1,
      type: Number
    }
  },
 methods: {
    textChange (value) {
        this.$emit('input', value)
      }
    },
    textEntry (value) {
      // This is to cover for situations where the change event runs first
      if (value.toUpperCase() === this.input.toUpperCase()) return
      if (this.debounce >= 0) {
        this.emitValue(value)
      } else {
        this.$emit('input', value)
      }
    }
  },
  async mounted () {
    this.emitValue = debounce(value => {
      this.$emit('input', value)
    }, Math.abs(this.debounce))
    await this.$nextTick()
    this.textChange(this.input) // apply whatever was loaded, and allow bindings to run
  }
Trevor
  • 2,792
  • 1
  • 30
  • 43