vue-router
vue-router copied to clipboard
Not able to update query parameter from navigation guard
Version
3.0.2
Reproduction link
jsfiddle.net/bqaxhgkc
Steps to reproduce
Inside beforeEnter try to modify query parameters by passing next({ query: {'my-param': 'new-value'} })
What is expected?
Query parameter will be updated with the new value and the URL will also update.
What is actually happening?
URL still having the same old value for my-param.
Even though the query parameter value is not updated in the URL, this.$route.query['my-param'] value is updated with the new value.
I'm realizing that calling next like the fiddle should create an infinite redirect, the same as doing
next({ name: 'foo', query: {'my-param': 5} })
which does create an infinite redirect. So I think this is technically a bug and I don't know why I didn't comment the workaround back then, but you can do this:
beforeEnter: (to, from, next) => {
// avoid an infinite redirection
if (String(to.query['my-param']) === '5') return next()
// make sure to include `name`
next({ name: 'foo', query: {'my-param': 5} })
}
Edit: proper version: https://jsfiddle.net/bqaxhgkc/ bug: clicking a second time the link should not change the location
Hello, I am trying to do something similar... but not quite. Basically I have a situation where I do have query parameters not tied to any route in particular, but that I would like to carry over through routes if they are present.
I am trying this, but is not working:
router.beforeEach((to, from, next) => {
const query = { ...to.query, ...configurationService.getURLCarryOverParams()};
// Replace the query params adding the non-route related query params that
// we want to carry over from page to page
next({
query: query
});
});
There is any workaround for this situation? I also tried to assign the "query" of the "to" route but it is read only.
@JohnBernardsson I would override the router's push method to implicitly pass the previous query so you don't have to write this everywhere:
router.push({ name: 'thing', query: { ...$route.query }})
@posva you mean overriding the library push method itself? Interesting... ok, I'll give it a go, see how that works.
Thanks!
Just in case someone reaches this, and have the same problem (or something similar), I easily solved overriding the push method as @posva mentioned.
Code uses ES6 classes:
import VueRouter from 'vue-router';
/**
* @class
* Extends Vue Router, to add specific push logic
*/
class CustomVueRouter extends VueRouter {
/**
* Overrides the Vue Router push method, to allow carrying over to all our pages
* some queryparams, if they were present in first load
* @param {RawLocation} location
* @param {Function} [onComplete]
* @param {ErrorHandler} [onAbort]
*/
push(location, onComplete, onAbort) {
const
staticQueryParams = {
// Logic to get the params to carry over
},
newLocation = {...location,
query: {
...(location.query || {}), ...staticQueryParams
}
};
// Calls the VueRouter push method
super.push(newLocation, onComplete, onAbort);
}
}
This is a major flaw with Vue Router. It really shouldn't be this difficult in passing a query object. I've spent hours dealing with every problem everyone has mentioned in this thread.
Needs to be completely redone, because this is just terrible. And the documentation everywhere is outdated.