[javascript] How to set URL query params in Vue with Vue-Router

I am trying to set query params with Vue-router when changing input fields, I don't want to navigate to some other page but just want to modify url query params on the same page, I am doing like this:

this.$router.replace({ query: { q1: "q1" } })

But this also refreshes the page and sets the y position to 0, ie scrolls to the top of the page. Is this the correct way to set the URL query params or is there a better way to do it.


Edited:

Here is my router code:

export default new Router({
  mode: 'history',
  scrollBehavior: (to, from, savedPosition)  => {
    if (to.hash) {
      return {selector: to.hash}
    } else {
      return {x: 0, y: 0}
    }
  },
  routes: [
    ....... 
    { path: '/user/:id', component: UserView },
  ]
})

This question is related to javascript vue-router vue.js

The answer is


To set/remove multiple query params at once I've ended up with the methods below as part of my global mixins (this points to vue component):

    setQuery(query){
        let obj = Object.assign({}, this.$route.query);

        Object.keys(query).forEach(key => {
            let value = query[key];
            if(value){
                obj[key] = value
            } else {
                delete obj[key]
            }
        })
        this.$router.replace({
            ...this.$router.currentRoute,
            query: obj
        })
    },

    removeQuery(queryNameArray){
        let obj = {}
        queryNameArray.forEach(key => {
            obj[key] = null
        })
        this.setQuery(obj)
    },

this.$router.push({ query: Object.assign(this.$route.query, { new: 'param' }) })

I normally use the history object for this. It also does not reload the page.

Example:

history.pushState({}, '', 
                `/pagepath/path?query=${this.myQueryParam}`);

Without reloading the page or refreshing the dom, history.pushState can do the job.
Add this method in your component or elsewhere to do that:

addParamsToLocation(params) {
  history.pushState(
    {},
    null,
    this.$route.path +
      '?' +
      Object.keys(params)
        .map(key => {
          return (
            encodeURIComponent(key) + '=' + encodeURIComponent(params[key])
          )
        })
        .join('&')
  )
}

So anywhere in your component, call addParamsToLocation({foo: 'bar'}) to push the current location with query params in the window.history stack.

To add query params to current location without pushing a new history entry, use history.replaceState instead.

Tested with Vue 2.6.10 and Nuxt 2.8.1.

Be careful with this method!
Vue Router don't know that url has changed, so it doesn't reflect url after pushState.


Here's my simple solution to update the query params in the URL without refreshing the page. Make sure it works for your use case.

const query = { ...this.$route.query, someParam: 'some-value' };
this.$router.replace({ query });

For adding multiple query params, this is what worked for me (from here https://forum.vuejs.org/t/vue-router-programmatically-append-to-querystring/3655/5).

an answer above was close … though with Object.assign it will mutate this.$route.query which is not what you want to do … make sure the first argument is {} when doing Object.assign

this.$router.push({ query: Object.assign({}, this.$route.query, { newKey: 'newValue' }) });

If you are trying to keep some parameters, while changing others, be sure to copy the state of the vue router query and not reuse it.

This works, since you are making an unreferenced copy:

  const query = Object.assign({}, this.$route.query);
  query.page = page;
  query.limit = rowsPerPage;
  await this.$router.push({ query });

while below will lead to Vue Router thinking you are reusing the same query and lead to the NavigationDuplicated error:

  const query = this.$route.query;
  query.page = page;
  query.limit = rowsPerPage;
  await this.$router.push({ query });

Of course, you could decompose the query object, such as follows, but you'll need to be aware of all the query parameters to your page, otherwise you risk losing them in the resultant navigation.

  const { page, limit, ...otherParams } = this.$route.query;
  await this.$router.push(Object.assign({
    page: page,
    limit: rowsPerPage
  }, otherParams));
);

Note, while the above example is for push(), this works with replace() too.

Tested with vue-router 3.1.6.


Actually you can just push query like this: this.$router.push({query: {plan: 'private'}})

Based on: https://github.com/vuejs/vue-router/issues/1631


Examples related to javascript

need to add a class to an element How to make a variable accessible outside a function? Hide Signs that Meteor.js was Used How to create a showdown.js markdown extension Please help me convert this script to a simple image slider Highlight Anchor Links when user manually scrolls? Summing radio input values How to execute an action before close metro app WinJS javascript, for loop defines a dynamic variable name Getting all files in directory with ajax

Examples related to vue-router

How can I go back/route-back on vue-router? Vuejs: Event on route change How to VueJS router-link active style How to add external JS scripts to VueJS Components VueJs get url query Do we have router.reload in vue-router? How to pass a value from Vue data to href? How to set URL query params in Vue with Vue-Router Vue-router redirect on page not found (404) Can vue-router open a link in a new tab?

Examples related to vue.js

How to fix 'Unchecked runtime.lastError: The message port closed before a response was received' chrome issue? Center content vertically on Vuetify Vue.js get selected option on @change Using Environment Variables with Vue.js did you register the component correctly? For recursive components, make sure to provide the "name" option Vue 'export default' vs 'new Vue' How can I go back/route-back on vue-router? Change the default base url for axios How to reference static assets within vue javascript How to change port number in vue-cli project