Vue Router: Keep query parameter and use same view for children
Solution 1
You can resolve this in the global hooks of Router
import VueRouter from 'vue-router';
import routes from './routes';
const Router = new VueRouter({
mode: 'history',
routes
});
function hasQueryParams(route) {
return !!Object.keys(route.query).length
}
Router.beforeEach((to, from, next) => {
if(!hasQueryParams(to) && hasQueryParams(from)){
next({name: to.name, query: from.query});
} else {
next()
}
})
If the new route (to
) does not have its own parameters, then they will be taken from the previous route (from
)
Solution 2
You can add in a mounted
hook a router navigation guard beforeEach
like this preserveQueryParams
:
// helpers.js
import isEmpty from 'lodash/isEmpty';
const preserveQueryParams = (to, from, next) => {
const usePreviousQueryParams = isEmpty(to.query) && !isEmpty(from.query);
if (usePreviousQueryParams) {
next({ ...to, query: from.query });
} else {
next();
}
};
// StartComponent.vue
removeBeforeEachRouteGuard: Function;
mounted() {
this.removeBeforeEachRouteGuard = this.$router.beforeEach(preserveQueryParams);
}
// don't forget to remove created guard
destroyed() {
this.removeBeforeEachRouteGuard();
// resetting query can be useful too
this.$router.push({ query: {} });
}
Related videos on Youtube
offz
Updated on September 15, 2022Comments
-
offz over 1 year
I'm rewriting an existing Angular 1 application with Vue.
The application always needs to authenticate an user by
locale
,id
andtoken
before entering any views. Respecting the conventions of our API, I specified thetoken
as a query parameter within my main parent route.Coming from the existing Angular's UI router implementation I thought this is the way to go:
// main.js new Vue({ el: '#app', router, store, template: '<router-view name="main"></router-view>' }) // router.js const router = new Router({ mode: 'history', routes: [ { name: 'start', path : '/:locale/:id', // /:locale/:id?token didn't work query: { token: null }, beforeEnter (to, from, next) { // 1. Get data from API via locale, id and token // 2. Update store with user data }, components: { main: startComponent }, children: [{ name: 'profile', path: 'profile', components: { main: profileComponent } }] } ] })
When I navigate to the
profile
view, I expect the view to change and the query token to stay, e.g./en-US/123?token=abc
to/en-US/123/profile?token=abc
. Neither happens.I'm using Vue 2.3.3 and Vue Router 2.3.1.
Questions:
- Can I keep query parameters when navigating to child routes?
- Am I using the Vue router right here? Or do I need to blame my UI router bias?
-
oliverpool about 6 yearsActually using
toWithQuery = Object.assign({}, to, {query: from.query});next(toWithQuery);
is more robust -
Kuba almost 6 years@oliverpool +1, I had troubles with going back to the root page without this. p.s. this looks like one of ways to handle localization so I'm surprised there isn't so much more to read about this use case.
-
Darky WC over 3 yearsThank you very much for this! More note to that is
next()
must be the last navigation call for Vue Router to know when should it stop going to the next page. -
Adam Jagosz over 3 yearsI have optional dynamic routes so my routing chokes on this when there are params. This works though:
next({ ...to, query: from.query });
-
Dmitriy over 2 yearsWhat to do if you need to erase query? This solution is bugging.