How to set vue router navigation guards to route to child routes without getting an infinite loop? - vue-router

My routes have a parent path with children. How can I set a navigation guard on the parent route to route to the children without it triggering an infinite loop?
This beforeEnter loops as it is called when I navigate to 'path/parent/child1' or 'path/parent/child2'
path: "path/parent",
beforeEnter: (to, from, next) => {
if(checkSomethingInDB) {
if(checkSomethingElseInDB){
next()
}else{
next({name: 'child1'})
} else {
next({name: 'child2})
}
}
...

Related

vue router route guard check vuex state

I have a route guard that looks like this. It checks the vuex store for a property, which is fetched async on page load. Since the code runs before the property is set, it always resolves as false.
Any ideas for a work around or a proper implementation?
router.beforeEach(async (to, from, next) => {
if (to.matched.some(record => record.meta.requiresActivated)) {
if (store.state.account.post_title !== 'true') {
next({
path: '/activate',
query: { redirect: to.fullPath, id: store.state.user.id }
})
}
next()
} else {
next()
}
})

Prevent route change within Vue compnent

Is it possible to prevent a route change within a Vue Component (not within my router file)?
My situation uses the same component, but the URL changes (/users/1 -> /users/2)
Vue.extend({
data: () => ({
active: true
}),
beforeRouteLeave(to, from, next){
if (this.active) {
// do not redirect
} else {
next();
}
}
})
My understanding is that this doesn't work when navigating the URL but the View/Component stays the same.
I need to use beforeRouteUpdate instead of beforeRouteLeave as stated in the docs
beforeRouteUpdate(to, from, next) {
if (this.active) {
next(false);
} else {
next();
}
},
If I'm using beforeRouteUpdate route url path in the browser not getting update, so I used beforeRouteLeave which is updating url and stop reloading same page.
beforeRouteLeave(to, from, next) {
if (this.active) {
next(false);
} else {
next();
}
}

trigger function after mounting any page in nuxt

Is it possible to write middleware in Nuxt to be triggered after mounting any page.
If I use the following middleware
export default function ({ app }) {
if (!process.server) {
app.$somePluginFunction()
}
}
it is triggered when navigating to that page, thus before mounting it. That is not what I am looking for.
I also know you can use the mounted() hook on an individual page, which is what I want, but I don't want to write the same mounted() hook to every page in my app manually. How can I do this?
There is many way to trigger a function before route change:
First use in default layout
// layout/default.vue
export default {
watch: {
$route () {
console.log('route changed', this.$route)
}
},
}
Second use before route:
https://router.vuejs.org/guide/advanced/navigation-guards.html#in-component-guards
router.beforeEach((to, from, next) => {
if (to.name !== 'Login' && !isAuthenticated) next({ name: 'Login' })
else next()
})
Third write plugin like this:
how to write global router-function in nuxt.js
And write mixin like this :
Run function AFTER route fully rendered in Nuxt.js

`this` undefined in vue-router beforeEach

I'm trying to access the session in vue-router viathis.a.app, but it pops out 1 error.
After i debug, i found out that this is undefined.
this is the code im using to show this.
I had tried to use function(to, from, next) {...} instead of es6 syntax, but this is still undefined.
router.beforeEach((to, from, next) => {
if (!to.meta.isPublic){
// eslint-disable-next-line
console.log(this)
}
next()
})
Is there any configuration i need to make so that i can access this in vue-router?
Yes, you can use access "this" inside router beforeEach hook, but in a different way. The router has the root instance from where it is inserted
User router.app it is pointing to "this" (the root Vue instance)
router.beforeEach((to, from, next) => {
if (!to.meta.isPublic){
// eslint-disable-next-line
console.log(router.app)
}
next()
})
My best solution is to use Vue's nextTick
<script> // ignore this tag, it's just for hightlight
router.beforeEach((to, from, next) => {
// console.info('TO', to, 'FROM', from)
Vue.nextTick(() => {
if (newTerm !== oldTerm) {
router.app.getEasy(newTerm)
}
})
next()
})
</script>

problem in redirecting in guarded route - Vue js Router

I have this route in my vue router.js file .
routes: [{
path: "/",
component: Home,
beforeEnter: (to, from, next) => {
if (!store.state.is_login) {
next('/login')
}
next()
}
}]
I use beforeEnter option for redirecting user if store.state.is_login === true
first problem :
so when I enter the url in browser I will redirect to /login page. this is works fine. but when I click the logo button, this beforeEnter function is not working.
this is my button that uses :
<router-link to="/" class="bp-logo"><Logo />home</router-link>
the second problem is :
is_login is in my store.state.is_login
I am storing my token in the localStorage
user_info is in store.state.user
problem :
condition 1: if !is_login redirect to /login .
condition 2 : if token exists and !is_login => request to backend /user with token and get user_info and set is_login true.
condition 3 : if !is_login && !token redirect to /login
You need to change your beforeEnter method to access the store instance. Rewrite like this:
beforeEnter: (to, from, next) => {
if (!this.$store.state.is_login) {
next('/login')
}
next()
}
I figured it out somehow. the first problem was when you render a route .then you are click for getting to that route again the function router.beforeEach not trigger. so I find another method in documentation.
routes: [{
path: "/",
component: Home,
beforeEnter: isAuthenticated,
}]
and this is my custom function for handling both problems .
const isAuthenticated = (to, from, next) => {
if (!store.state.is_login) {
if ((localStorage.getItem('token')) && (lodash.isEmpty(store.state.user))) {
let headers = {
headers: {
Authorization: localStorage.getItem("token"),
"Access-Control-Allow-Origin": "*"
}
};
axios
.get(`${store.state.api}admin/user`, headers)
.then(response => {
store.state.user = response.data.user;
store.state.is_login = true;
next("/");
})
.catch(error => {
store.state.Error = error;
next('/login')
});
}
next('/login')
return
}
next()
return
}