I have a Vue 2 application that uses an array of objects to back a search/multiselect widget provided by vue-multiselect.
I have looked at the Vue 1 -> 2 migration guide on debouncing calls, but the example they give did not propagate the arguments from the DOM elements to the business logic.
Right now the select fires change events with every keystroke, but I would like to throttle this (EG with lodash#throttle) so I'm not hitting my API every few milliseconds while they're typing.
import {mapGetters} from 'vuex';
import { throttle } from 'lodash';
import Multiselect from 'vue-multiselect'
export default {
components: {
Multiselect
},
data() {
return {
selectedWork: {},
works: [],
isLoading: false
}
},
computed: {
...mapGetters(['worksList']),
},
methods: {
getWorksAsync: throttle((term) => {
// the plan is to replace this with an API call
this.works = this.worksList.filter(work => titleMatches(work, term));
}, 200)
}
}
Problem: when the user types in the select box, I get the error:
TypeError: Cannot read property 'filter' of undefined
which is happening because this.worksList
is undefined
inside the throttle
function.
Curiously, when I use the dev tools debugger, this.worksList
has the value I need to dereference, with this
referring to the Vue component.
Currently I am not calling the API from within the component, but the problem remains the same:
this
context to update my this.works
list? EDIT: this is explained in Vue Watch doesnt Get triggered when using axios
What is the proper pattern in Vue 2?
I ran into the same issue when using lodash.debounce
. I'm a huge fan of arrow syntax, but I discovered that it was causing _.throttle()
and _.debounce()
, etc. to fail.
Obviously my code differs from yours, but I have done the following and it works:
export default {
...,
methods: {
onClick: _.debounce(function() {
this.$emit('activate', this.item)
}, 500)
}
}
Even though I'm not using arrow syntax here, this
still references the component inside the debounced function.
In your code, it'd look like this:
export default {
...,
methods: {
getWorksAsync: throttle(function(term) {
// the plan is to replace this with an API call
this.works = this.worksList.filter(work => titleMatches(work, term));
}, 200)
}
}
Hope that helps!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With