Struggling to convert my VueJS component from JavaScript to TypeScript, feeling a bit lost

I am new to VueJS and I am facing a challenge converting my VueJS project to use TypeScript. I have been trying to bind functions to certain variables in JavaScript, but I am struggling with accomplishing the same in TypeScript. Even though there are no errors reported in the developer tools, I am unable to get the route.query for VueJS to change.

My goal is to create a component similar to an auto search feature. I believe I might have used lodash incorrectly in TypeScript, but it's possible that my entire code needs correction. The code provided below showcases just one component, but there is another component, CharacterCard, that also monitors event changes on router.query and sends a request to the server to fetch data based on the user query. Are there better approaches or methods to implement this functionality?

If you require more information, please let me know.

<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>

Answer №1

The problem lies in the way _.debounce is being utilized here. When using the debounce function, a new debounced function is returned but not executed immediately. In the current implementation of searchCharacter, a debounced function is created but not invoked.

To resolve this issue, one approach is to define the debounced function outside of searchCharacter and then call it when needed:

  @Watch("search")
  public searchCharacter(value: any) {
    this.debouncedSearchCharacter(value)
  }

  public debouncedSearchCharacter = _.debounce((value) => {
    // handle route query
    let route: any = {
      name: "characters",
    }

    if (value !== "") {
      route.query = {
        search: value,
      }
    }

    if (this.$route.name === "characters") {
      this.$router.push(route)
    }
  }, 700)

Answer №2

After some digging, I managed to solve the problem by following this discussion:

https://github.com/vuejs-templates/browserify-simple/issues/6

As a result, here is my updated code snippet specifically for implementing debounce:

public debouncedSearchCharacter = _.debounce((search) => {
    this.searchFinder(search);
}, 700);

public searchFinder(search) {
    if (this.startSearch) {
        // Handle 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 turned out to be related to the arrow function: as suspected, it was binding the keyword/property "this" to the parent context, causing the debounce function to lose its reference to "this." With that fixed, my router is now correctly defined and this.$router.push(route) is functioning as expected.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

The default selection in res.format is not being properly recognized

When I make a request with the accept header set as "application/json, text/javascript, */*; q=0.01", the response is always in HTML format instead of the default format specified. It seems like something is missing here. Given that the header does not spe ...

Error Checking in AngularJS Form Submission

According to my form.json file, I have a form that needs validation and a simulated submission. Firstly, I need to address this issue: fnPtr is not a function Next, I want to submit the form to a mocked API endpoint that will return true or false. Can I ...

Unusual behavior observed in AngularJs local variables

This code snippet is from the controller: cat1=[]; $.getJSON('categories/1/', function(data) { cat1 = data; //this returns a JSON object }); //cat2..4 are also JSONs $scope.pictures=[cat1,cat2,cat3,cat4,cat5]; The issue here seems to be th ...

Error rendering {message} object on the Chrome Console

In my ReactJS component, I am utilizing the {message} parameter from props. Check out the code snippet below: import React from "react"; const MyMessage = ({ message }) => { if (message?.attachments?.length > 0) { return ( < ...

Modifying the content of a paragraph by incorporating information from various sources

I need a way to input measurements for my items in text fields, and then with the click of a button, transfer those measurements into a paragraph in corresponding fields. The code I am currently using is shown below: <!DOCTYPE html> <html> & ...

Display Nested Data in Angular Material Table: A Step-by-Step Guide

I recently received a REST API response from the following URL: { "list": [ { "id": 1, "login": "<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="7c08190f08234d3c0508521f1311"& ...

Modify the heading color of elements in a class to a distinct color when the cursor hovers over the element

I currently have 3 heading elements: elem1, elem2, and elem3. When I hover over elem1, I want elem1 to turn yellow and elem2 and elem3 to turn purple. If I hover over elem2, I want elem2 to be yellow and the others to be purple. Once I release the hover, I ...

Unveiling the Magic: Enhancing Raphaeljs with Interactive Click Events on a Delicious Slice of the

I'm having trouble responding to a click event on each slice of a Raphael Pie Chart. I've tried implementing the code below, but it doesn't seem to be working. The code is just two lines, commented as "My Code", in the example from the offic ...

Using jQuery to refresh a div element

I am struggling with updating the "right" div in my jsp page using the script below. Despite being contained in a single file, the update does not seem to work. Any assistance is appreciated. <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//E ...

I'm curious, what is the exact function of ...state?

Just dipping my toes into NgRx (redux) within Angular and I'm a bit puzzled by the use of ...state in the code snippet below. My understanding is that it functions as spread operator, but I can't grasp why the data attributes from the Interface S ...

Adjust the background color of child divs when the parent div is being hovered over

I am facing a challenge with my current setup: <div class="parent"> <div class="child"> </div> <div class="child"> </div> <div class="child"> </div> </div> My goal is to change the background co ...

Troubleshooting Key Press Issues with Bootstrap 5 Dropdown and Collapse Feature

Exploration In my quest to create a dynamic Bootstrap (5) Navigation bar/menu with animated sub-menus, I stumbled upon a solution that seems to fit the bill perfectly. By employing data-bs-toggle="collapse" instead of 'dropdown', I dis ...

Dynamic Filtering of HTML Dropdown Options Based on Another Dropdown Selection

I am facing an issue with multiple HTML dropdowns. My requirement is that upon selecting an option from one dropdown, the next dropdown should get automatically populated. The data to populate these dropdowns is fetched from a database using SQL statements ...

What is the best way to send props (or a comparable value) to the {children} component within RootLayout when using the app router in Next.js

As I work on updating an e-commerce website's shopping cart to Next.js 13+, I refer back to an old tutorial for guidance. In the previous version of the tutorial, the _app.ts file utilized page routing with the following code snippet: return ( < ...

What is the solution to fixing the error message "SyntaxError: missing ) after argument list" in JavaScript?

I wrote some code in HTML/JavaScript/PHP, and in the 3rd echo statement, I added a button that calls the deleteAttribute() function when clicked. However, I encountered an error at the 3rd echo statement with (type = "button"): "Uncaug ...

Passing a single item from a list as a prop in Vue.js

Imagine having the following set of information in data: data: { todos: [ { id: 1, title: "Learn Python" }, { id: 2, title: "Learn JS" }, { id: 3, title: "Create WebApp" } ] } Now, I aim to send only the item with an id of 2 t ...

ui-jq flot graph with lazy loading

I am working with this HTML code: <div id="test" ui-jq="plot" ui-options=" [ { data: {{line}}, points: { show: true, radius: 6}, splines: { show: true, tension: 0.45, lineWidth: 5, fill: 0 }, label: 'Akademi' }, ], { ...

The switch case functionality refuses to change when I interact with the user interface

Can someone please help me troubleshoot? I'm not receiving any errors in the Chrome console. HTML <div class="wrapper"> <i id="repeat" class="fas fa-stop-circle"></i> </div> Javascript const wrap ...

Performing a modulo operation within a v-for loop

I'm showcasing divs in a loop and I need to assign classes based on the loop index. My goal is to have index 0 and 1 with the class col-6, then indexes 2,3,4 with the class col-4, followed by index 5 and 6 having the class col-6, and so forth. This w ...

What is the best way to choose a random ID from a table within specified time intervals in MySQL?

I need to retrieve a random ID from the table nodes within the last 15 seconds. I attempted the following code, but it produced a lengthy output: const mysql = require('mysql'); const connection = mysql.createConnection({ host ...