Andrew Kim
Andrew Kim

Reputation: 3335

vue-router- way to persist query param from old route to new route

For every route in my application, if there's a certain query param, let's call it userId, I would like the next route to also contain that query param.

One solution is to modify every router-link and router.push to add this query param, but I'd like to use router.beforeEach to solve this problem.

I tried this, but it starts an infinite loop:

router.beforeEach((to, from, next) => {
  if (from.query.userId) {
    next({
      path: to.path,
      query: Object.assign({}, to.query, from.query.userId),
    })
  }
  next()
})

Is there any way in vue-router that allows me to persist a query param if it exists in the previous route?

Upvotes: 3

Views: 5077

Answers (1)

AndrewShmig
AndrewShmig

Reputation: 4923

I was stumbling across the same problem and here is my production solution:

router.beforeEach((to, from, next) => {
    let requiresAuth = (to.meta.hasOwnProperty('requiresAuth') ? to.meta.requiresAuth : true);

    //... comment
    if (!store.getters.isAuthenticated() && requiresAuth) {
        next({name: 'login', params: {...{redirect: to.name}, ...to.params}});
        return;
    } else if (store.getters.isAuthenticated() && !store.getters.isDataPreloaded() && to.name !== 'preloading') {
        //... comment
        next({name: 'preloading', params: {...{redirect: to.name}, ...to.params}});
        return;
    }

    next();
})

It doesn't matter what you use - query or params. Don't forget that you can use optional parameters to tell while redirecting that something is happening. You can add an optional param like redirected and check it in your beforeEach method, if it is set to true - perform one action, if it is set to false - perform another action.

Remember that with params property you can exchange between routes with absolutely any data (JS objects) you want without showing this data to your users in URLs.

Let me explain why and how my code works:

  1. User opens a page example.com/my-private-zone/dashboard/reports
  2. System checks if he is already authenticated, if not - save from route and redirect to login page - example.com/login.
  3. User authenticates
  4. User is being redirected to preloading page (example.com/preloading) where all the needed JS scripts are preloaded.
  5. User is being redirected to the route from the 0-step. As you can see I am passing the user entry point (as redirect param) for the final redirect without changing URL that is being displayed to a user.

Your code also should be fine, you forgot to add a return statement in your if branch:

router.beforeEach((to, from, next) => {
  if (from.query.userId) {
    next({
      path: to.path,
      query: Object.assign({}, to.query, from.query.userId),
    })
    return;
  }
  next()
})

Hope this helps!

Upvotes: 1

Related Questions