3

I am doing the search engine section in VueJS and Laravel, but I have a problem that does not allow me to advance in the other sections. The search engine opens and everything but when I write it only sends the first letter or 2 but not all of them like this in this image:

image of the data you send

the data that I write

After that it shows me the following error in console:

Uncaught (in promise) NavigationDuplicated: Avoided redundant navigation to current location: "/search?q=th"

Now showing my search engine code:

<template>
  <div class="form_MCycW">
    <form autocomplete="off" @sumbit.prevent>
      <label class="visuallyhidden" for="search">Search</label>

      <div class="field_2KO5E">
        <input id="search" ref="input" v-model.trim="query" name="search" type="text" placeholder="Search for a movie, tv show or person..." @keyup="goToRoute" @blur="unFocus">

        <button v-if="showButton" type="button" aria-label="Close" @click="goBack">
          <svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 15 15"><g fill="none" stroke="#fff" stroke-linecap="round" stroke-miterlimit="10" stroke-width="1.5"><path d="M.75.75l13.5 13.5M14.25.75L.75 14.25"/></g></svg>
        </button>
      </div>
    </form>
  </div>
</template>

<script>
  import { mapState } from 'vuex';

  export default {
    data() {
      return {
        query: this.$route.query.q ? this.$route.query.q : ''
      }
    },

    computed: {
       showButton() {
           return this.$route.name === 'search';
       },

       ...mapState({
         search: state => state.event.fromPage
       })
     },

     mounted() {
       this.$refs.input.focus();
     },

     methods: {
       goToRoute() {
         if (this.query) {
           this.$router.push({
             name: 'search',
             query: { q: this.query },
           });
         } else {
           this.$router.push({
             path: this.fromPage,
           });
         }
       },

       goBack() {
         this.query = '';

         this.$router.push({
           path: '/',
         });
       },

       unFocus (e) {
         if (this.$route.name !== 'search') {
           const target = e.relatedTarget;

           if (!target || !target.classList.contains('search-toggle')) {
             this.query = '';
             this.$store.commit('closeSearch');
           } 
         }
       }
     }
   }
</script>

This is the other section of the search engine:

<template>
  <main class="main">
    <div class="listing">
      <div class="listing__head"><h2 class="listing__title">{{ title }}</h2></div>
      <div class="listing__items">
        <div class="card" v-for="(item, index) in data.data" :key="index">
          <router-link :to="{ name: 'show-serie', params: { id: item.id }}" class="card__link">
            <div class="card__img lazyloaded"><img class="lazyload image_183rJ" :src="'/_assets/img/covers/posters/' + item.poster" :alt="item.name"></div>
            <h2 class="card__name">{{ item.name }}</h2>
            <div class="card__rating">
              <div class="card__stars"><div :style="{width: item.rate * 10 + '%'}"></div></div>
              <div class="card__vote">{{ item.rate }}</div>
            </div>
          </router-link>
        </div>
      </div>
    </div>
  </main>
</template>
<script>
  import { mapState } from 'vuex';
  let fromPage = '/';

  export default {
    name: "search",

    metaInfo: {
       bodyAttrs: {
        class: 'page page-search'
       }
    },

    computed: {
      ...mapState({
        data: state => state.search.data,
        loading: state => state.search.loading
      }),

      query() {
        return this.$route.query.q ? this.$route.query.q : '';
      },

      title() {
        return this.query ? `Results For: ${this.query}` : '';
      },
    },

    async asyncData ({ query, error, redirect }) {
      try {
        if (query.q) {
          this.$store.dispatch("GET_SEARCH_LIST", query.q);
        } else {
          redirect('/');
        }
      } catch {
         error({ message: 'Page not found' });
      }
    },

    mounted () {
      this.$store.commit('openSearch');
      this.$store.commit('setFromPage', fromPage);

      if (this.data.length == 0 || this.data === null) {
        this.$store.dispatch("GET_SEARCH_LIST", this.query);
      }
      setTimeout(() => {
          this.showSlideUpAnimation = true;
      }, 100);
    },

    beforeRouteEnter (to, from, next) {
      fromPage = from.path;
      next();
    },

    beforeRouteUpdate (to, from, next) {
      next();
    },

    beforeRouteLeave (to, from, next) {
      const search = document.getElementById('search');

      next();

      if (search && search.value.length) {
        this.$store.commit('closeSearch');
      }
    }
  };
</script>

In my routes section it is defined as follows:

{
  name: 'search',
  path: '/search',
  component: require('../views/' + themeName + '/control/search/index').default
}

It is supposed to be a real-time search engine. I would appreciate your help in solving this problem...

Elian Miranda
  • 195
  • 1
  • 11

1 Answers1

0

What you need is a debounce. What it does is that it wait or delay till the user had finished typing before the model get updated or before you send it to the server.

An example of how it works is here

Here is a package for it. https://github.com/vuejs-tips/v-debounce

Solar
  • 870
  • 9
  • 18