Home > Mobile >  Is it possible to use the beforeEnter navigation guard in Vue Router to redirect the user?
Is it possible to use the beforeEnter navigation guard in Vue Router to redirect the user?

Time:03-05

I'm building an SPA application using Vue2 and Vue Router 3.5

The application has two authentication routes, 'admin' and 'organisation'

I have the router setup so that each auth guard has it's own prefix in the url

'/auth/:guard'

'/organisation'

'/admin'

The router file looks like this:


const routes = [
    organisations,
    authRoutes,
]

const router = new VueRouter({
  mode: 'history',
  base: process.env.BASE_URL,
  routes
})

Inside of the organisations file, I return an object:

export default {
    path: '/organisations',
    meta: { auth: true, guard: 'organisations' },
    component: () => import('../views/Organisations/OrganisationContainer.vue'),
    beforeEnter: (to, from, next) => {
        return store.dispatch('authentication/check')
            .then(response => {
                if(response) {
                    if(response.guard == 'admin') {
                        return next('/admin')
                    }
                    if(response.guard != 'organisation') {
                        return false
                    }
                }else{
                    return next('/auth/organisation/login')
                }
            })
    },
    children: [
        {
            path: '/',
            name: 'organisation.dash',
            meta: { auth: true, route_identifier: 'dashboard', title: 'Dashboard' },
            component: () => import('../views/Organisations/Dashboard/Dashboard.vue')
        },
}

In previous projects I've used the router.beforeEach to handle navigation in the system.

The problem with router.beforeEach is that I don't want to have one large method to handle the navigation for every route in the system. It'd be a whole lot easier if I could just have something like

"If anyone tries to visit a /organisation route, and they aren't logged in, redirect the user to the route /auth/organisation/login, if they are logged in, but they are an admin, redirect the user to their dashboard."

I was planning to use beforeEnter to achieve this - but whenever I attempt to use the next() function to redirect, a blank white screen is returned. If I return the next() function without parameters, it doesn't redirect, but the page still loads.

I'm probably misusing the beforeEnter navigation guard - but does anyone know how I could redirect a user using the beforeEnter navigation guard, or achieve similar functionality without using beforeEach and having a large method to contend with?

Thanks in advance

CodePudding user response:

The problem with router.beforeEach is that I don't want to have one large method to handle the navigation for every route in the system.

There's nothing wrong with this approach at all, just make sure your code in beforeEach is fast (don't make API calls in beforeEach) and if you have a lot of code there's nothing stopping you split the code a bit into multiple functions so it's more readable.

However, if you really don't need to use beforeEach and you only have a few routes with specific requirements you can use beforeEnter but it's a bit different than beforeEach.. First of all, in the code snippet you provided you defined a beforeEach callback on the route, but beforeEach is a router level callback as described in docs.

You have to change your snippet and replace beforeEach with beforeEnter like this:

export default {
    path: '/organisations',
    meta: { auth: true, guard: 'organisations' },
    component: () => import('../views/Organisations/OrganisationContainer.vue'),
    beforeEnter: (to, from, next) => {
        return store.dispatch('authentication/check')
            .then(response => {
                if(response) {
                    if(response.guard == 'admin') {
                        return next('/admin')
                    }
                    if(response.guard != 'organisation') {
                        return false
                    }
                }else{
                    return next('/auth/organisation/login')
                }
            })
    },
    children: [
        {
            path: '/',
            name: 'organisation.dash',
            meta: { auth: true, route_identifier: 'dashboard', title: 'Dashboard' },
            component: () => import('../views/Organisations/Dashboard/Dashboard.vue')
        },
}

  • Related