Reputation: 189
I'm fairly new to VueJS. My problem is converting my vuejs project to vuejs using typescript. I have looked at binding functions to certain variables in javascript, but I'm lost about doing it in typescript. Below are my javascript code, and then my attempt to refactor it into typescript. There is no error showing in developer tools, however the route.query for vuejs is not changing at all.
What I'm trying to do is create a component that is like auto search. I'm positive the way I have used lodash for my typescript is incorrect, but maybe my entire code is incorrect. Below is just one component, but there is another component which is the CharacterCard that also watches for event change on the router.query and makes the get request to the server to fetch based on user query. Also, is there better ways to approach this method or a better way?
Please let me know if you need additional details.
<script>
import CharacterService from '../../services/characterService'
import CharacterCard from '../../components/_shared/CharacterCard.vue'
import Lodash from 'lodash'
export default {
components: {
CharacterCard
},
data () {
return {
dialog: false,
search: ''
}
},
methods: {
dialogAndSearchReset () {
this.search = ''
this.dialog = false
}
},
watch: {
// debounce of 700ms
search: Lodash.debounce(async function (value) {
// for route query
let route:any = {}
route = {
name: 'characters'
}
if (this.search !== '') {
route.query = {
search: this.search
}
}
// || this.$route.name === 'character'
if (this.$route.name === 'characters') {
this.$router.push(route)
}
}, 700),
'$route.query.search': {
immediate: true,
handler (value) {
this.search = value
}
},
$route (to, from) {
if (this.dialog === true && this.$route.name === 'character') {
this.dialogAndSearchReset()
}
}
}
}
</script>
My attempt:
<script lang="ts">
import { Component, Prop, Vue, Watch } from 'vue-property-decorator';
import CharacterSearchCard from './CharacterSearchCard.vue';
import _ from 'lodash';
@Component({
components: {
charactersearchcard: CharacterSearchCard,
},
})
export default class QuickSearch extends Vue {
// model for Dialog example
public customDialogModel: boolean = false;
public search: string = '';
// public quickSearch: any = this.$route.query.search || null; // the url search query
@Watch('search')
public searchCharacter(value: any) {
_.debounce(async () => {
// for route query
let route: any = {};
route = {
name: 'characters',
};
if (value !== '') {
route.query = {
search: value,
};
}
if (this.$route.name === 'characters') {
this.$router.push(route);
}
}, 700);
}
@Watch('$route.query.search', { immediate: true })
public searchHandler(value: any) {
this.search = value;
}
@Watch('$route')
public changeRoute(to, from) {
if (this.customDialogModel === true && this.$route.name === 'character') {
this.closeAndReset();
}
}
public closeAndReset() {
this.search = '';
this.customDialogModel = false;
}
public navigateTo(e) {
this.$router.push({
name: e,
});
}
}
</script>
Upvotes: 2
Views: 720
Reputation: 189
I figured it out based off of this thread:
https://github.com/vuejs-templates/browserify-simple/issues/6
With that, my new code just in regards to using debounce is this:
public debouncedSearchCharacter = _.debounce((search) => {
this.searchFinder(search);
}, 700);
public searchFinder(search) {
if (this.startSearch) {
// for route query
// first check if modal is open
let route: any = {};
route = {
name: 'characters',
};
console.log(`search searching: ${search}`);
console.log('in debounce search');
if (search !== '') {
route.query = {
search,
};
}
console.log(`what route: ${route}`);
if (this.$route.name === 'characters') {
console.log(this.$router.currentRoute);
this.$router.push(route);
}
}
}
The issue was being the arrow function: like I kind of suspected was binding keyword/property, this, to the parent context, which was the debounce function as the one in context with no reference to this. Now my router is able to be defined and this.$router.push(route) works.
Upvotes: 1
Reputation: 12018
The issue here is with the usage of _.debounce
. The debounce function returns a new function to be debounced, but doesn't actually call anything. With the way it's currently being used in searchCharacter
, it creates a new debounced function, but doesn't do anything with it.
One way to fix this would be to create the debounced function outside of searchCharacter
, then call it:
@Watch("search")
public searchCharacter(value: any) {
this.debouncedSearchCharacter(value)
}
public debouncedSearchCharacter = _.debounce((value) => {
// for route query
let route: any = {
name: "characters",
}
if (value !== "") {
route.query = {
search: value,
}
}
if (this.$route.name === "characters") {
this.$router.push(route)
}
}, 700)
Upvotes: 3