2

I am using Vue.js 2.6 with the vue-router component. I have a search form as follows:

<form class="search-form" @submit.prevent="search">
    <div class="form-group">
        <input type="text" class="form-control" v-model="term" placeholder="Search">
    </div>
</form>

And here is my script:

<script>
  export default {
    data() {
      return {
        term: this.$route.query.term,
        items: []
      }
    },
    created() {
      if (this.term != null) {
        this.search()
      }
    },
    watch: {
      '$route.query.term'() {
        this.term = this.$route.query.term
        this.search()
      }
    },
    methods: {
      search: function () {
        window.axios.get('/images/search', {
          params: {
            term: this.term
          }
        })
        .then(response => {
          this.$router.push({query: { 'term' : this.term}})
          this.items = response.data.collection.items
        })
        .catch(error => {
          return error
        })
      }
    }
  }
</script>

What I am trying to achieve with this code is the following:

  1. User submits form, the search() function is called. The URL is updated with the query param, e.g. /search?term=<term>. This is working but the search() function is being called twice.
  2. User carries out several searches, then presses the back button. The search field in the form is updated and the search is carried out. This is working but the search() function is being called twice.
  3. User manually enters query param in the URL bar. The search field in the form is populated and the search is carried out. This is working.

Where the search() function is being called twice, this is due to the watch() function, which is designed to watch changes to the URL bar. I am not sure how to combine this function correctly with the search() function.

1 Answer 1

2

In watch, you can compare new value with old value, and only perform search when new value is different with old value

watch: {
  '$route.query.term'(newVal, oldVal) {
    if (newVal != oldVal) {
      this.term = this.$route.query.term
      this.search()
    }
  }
},

To make it call only 1 for 1st case, you might want to separate button click handler with real search call

<script>
  export default {
    data() {
      return {
        term: this.$route.query.term,
        items: []
      }
    },
    created() {
      if (this.term != null) {
        this.performSearch()
      }
    },
    watch: {
      '$route.query.term': {
        handler: function(newVal, oldVal) {
          if (newVal != oldVal) {
            this.term = this.$route.query.term
            this.performSearch()
          }
        },
        immediate: true 
      }
    },
    methods: {
      search: function () {
        // this is call when user click search Button
        this.$router.push({query: { 'term' : this.term}})

      },
      performSearch() {
        // perform actual searcch
        window.axios.get('/images/search', {
          params: {
            term: this.term
          }
        })
        .then(response => {
          this.items = response.data.collection.items
        })
        .catch(error => {
          return error
        })
      }
    }
  }
</script>
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.