How to set URL query params in Vue with Vue-Router

JavascriptVue Routervue.js

Javascript Problem Overview


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 },
  ]
})

Javascript Solutions


Solution 1 - Javascript

Here is the example in docs:

// with query, resulting in /register?plan=private
router.push({ path: 'register', query: { plan: 'private' }})

Ref: https://router.vuejs.org/en/essentials/navigation.html

As mentioned in those docs, router.replace works like router.push

So, you seem to have it right in your sample code in question. But I think you may need to include either name or path parameter also, so that the router has some route to navigate to. Without a name or path, it does not look very meaningful.

This is my current understanding now:

  • query is optional for router - some additional info for the component to construct the view
  • name or path is mandatory - it decides what component to show in your <router-view>.

That might be the missing thing in your sample code.

EDIT: Additional details after comments

Have you tried using named routes in this case? You have dynamic routes, and it is easier to provide params and query separately:

routes: [
    { name: 'user-view', path: '/user/:id', component: UserView },
    // other routes
]

and then in your methods:

this.$router.replace({ name: "user-view", params: {id:"123"}, query: {q1: "q1"} })

Technically there is no difference between the above and this.$router.replace({path: "/user/123", query:{q1: "q1"}}), but it is easier to supply dynamic params on named routes than composing the route string. But in either cases, query params should be taken into account. In either case, I couldn't find anything wrong with the way query params are handled.

After you are inside the route, you can fetch your dynamic params as this.$route.params.id and your query params as this.$route.query.q1.

Solution 2 - Javascript

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.

Solution 3 - Javascript

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

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

Solution 4 - Javascript

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.

Solution 5 - Javascript

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 });

Solution 6 - Javascript

Okay so i've been trying to add a param to my existing url wich already have params for a week now lol, original url: http://localhost:3000/somelink?param1=test1 i've been trying with:

this.$router.push({path: this.$route.path, query: {param2: test2} });

this code would juste remove param1 and becomes http://localhost:3000/somelink?param2=test2

to solve this issue i used fullPath

this.$router.push({path: this.$route.fullPath, query: {param2: test2} });

now i successfully added params over old params nd the result is

http://localhost:3000/somelink?param1=test1&param2=test2

Solution 7 - Javascript

My solution, no refreshing the page and no error Avoided redundant navigation to current location

    this.$router.replace(
      {
        query: Object.assign({ ...this.$route.query }, { newParam: 'value' }),
      },
      () => {}
    )

Solution 8 - Javascript

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

Solution 9 - Javascript

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' }) });

Solution 10 - Javascript

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)
	},

Solution 11 - Javascript

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

Example:

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

Solution 12 - Javascript

You could also just use the browser window.history.replaceState API. It doesn't remount any components and doesn't cause redundant navigation.

window.history.replaceState(null, null, '?query=myquery');

More info here.

Solution 13 - Javascript

The vue router keeps reloading the page on update, the best solution is

  const url = new URL(window.location);
  url.searchParams.set('q', 'q');
  window.history.pushState({}, '', url);
        

Solution 14 - Javascript

With RouterLink

//With RouterLink
<router-link 
  :to="{name:"router-name", prams:{paramName: paramValue}}"
>
Route Text
</router-link>

//With Methods

methods(){
  this.$router.push({name:'route-name', params:{paramName: paramValue}})
}

With Methods

methods(){
  this.$router.push({name:'route-name', params:{paramName, paramValue}})
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionSaurabhView Question on Stackoverflow
Solution 1 - JavascriptManiView Answer on Stackoverflow
Solution 2 - JavascriptManUtopiKView Answer on Stackoverflow
Solution 3 - Javascriptjean d'armeView Answer on Stackoverflow
Solution 4 - JavascriptAndre MView Answer on Stackoverflow
Solution 5 - Javascriptparker_codesView Answer on Stackoverflow
Solution 6 - JavascriptChiKa LiOView Answer on Stackoverflow
Solution 7 - Javascripthayumi kuranView Answer on Stackoverflow
Solution 8 - JavascriptBoston KenneView Answer on Stackoverflow
Solution 9 - JavascriptBorisView Answer on Stackoverflow
Solution 10 - Javascriptvir usView Answer on Stackoverflow
Solution 11 - JavascriptmostafaView Answer on Stackoverflow
Solution 12 - JavascriptLudolfynView Answer on Stackoverflow
Solution 13 - JavascriptSachin SView Answer on Stackoverflow
Solution 14 - JavascriptZakirsoftView Answer on Stackoverflow