Vue router beforeEach - vue.js

Problem is that the name gets undefined value I do not know why.
enter image description here
router.beforeEach((to, from, next) => {
console.dir(to);
});

assuming that you have router.js file or something similar your route object would look something like this
export default new Router({
routes: [
{
path: '/login',
name: 'login', // this being the name
component: () => import(whatever component),
meta: {
// some data goes here if needed
}
},
]
})
name: 'login' would be the undefined value you are seeing or what ever name you place there for whatever route

Related

Set page title dependent on Vue router params

I'm not sure if this is possible, but here goes:
I'm trying to make it so the page title (the meta tag) displays the username of the profile you're currently on. My code is as follows:
export default new Router({
mode: "history",
base: process.env.BASE_URL,
routes: [
{
path: "/profile/:userId/",
name: "profile",
component: Profile,
meta: {
title: "Profile - ((USERID HERE))", // <-- Find how to insert :userId into page title
},
},
Any advice on how to accomplish this, or if it's even possible to have dynamic page titles using vue router? Thanks.
you can use router props as function,
so instead of passing a prop of userId, pass a prop of title like so:
routes: [
{
path: "/profile/:userId",
name: "profile",
component: Profile,
props: route => ({ title: `Profile ${route.params.userId}` })
},
]
you can read more about this in vue docs
You would need to set the title on each router entry
const router = new Router({
mode: "history",
base: process.env.BASE_URL,
routes: [
{
path: "/profile/:userId/",
name: "profile",
component: Profile,
meta: {
title: "Profile - ((USERID HERE))", // <-- Find how to insert :userId into page title
},
},
//Other properties
})
router.beforeEach((to, from, next) => {
// You have access to the route here so you could dynamically get the variable? to.params? (Sorry for editing this post as didn't see the full question!)
document.title = to.meta.title ? to.meta.title : "Some Default Title"
// Edit 2 it seems params contains the thing you need so you could detect if to.meta.title is a thing and dynamically change it `Profile - (${to.params.userId})`
next() // You must call next!
})
export default router

prevent vue-router to open same path

can you give me some feedback about my solution?
I want to prevent vue router to open a site the user sees already.
The problem was: the user had open a site with a double id as paramters like this: path: '/detail/:idType/:itemId After a click on the same tab again the last id /:itemId was removed in the url and the user sees a different view, which I want to prevent.
My current solution is adding a navigation guard:
// router.js
router.beforeEach((to, from, next) => {
if (to.name === from.name) return
else next()
})
Is it okay to return if the names matches?
Do I use the correct router method?
thanks!
Edit for Praveen
// router.js
const router = new VueRouter({
routes: [
{
path: '/new',
name: 'New',
component: () => import('../layout/New'),
props: {
mode: 'create'
}
},
{
path: '/edit/:uuid',
name: 'Edit',
component: () => import('../layout/New'),
props: {
mode: 'edit'
}
},
{
path: '/detail/:idType/:itemId/:uuidId?',
name: 'Detail',
component: () => import('../layout/Detail'),
props: true,
}
],
mode: 'hash',
linkActiveClass: 'active'
})
// tab navigation
<b-link
:to="{ name: ['Edit', 'Detail'].indexOf($route.name) !== -1 ? $route.name : 'New'}"
class="btn btn-site-nav"
type="button"
v-text="'Booking'"
/>
To abort a navigation, call next(false) (in your case: if (to.name === from.name) next(false))
To allow it to pass (to its target), call next with undefined: next() (or next(undefined) - if you want to write more explicit code)
And to redirect it, call next with an object containing either name or path (i.e: next({ name: 'Login' }))

beforeEnter in Vue routes does not work for children routes

I am using vue 2.6.10 and in my vue's router.js I set some routes like so
Vue.use(Router)
const router = new Router({
mode: "history",
base: process.env.BASE_URL,
routes: [
{
path: '/login',
name: 'login',
component: Login,
},
{
path: '/shoes',
name: 'shoes',
component: Shoes,
beforeEnter: (to, from, next) => {
if (store.state.login.quad_token == null) {
next('/login');
}
next();
},
children:[
{
path: ':skateshoes',
name: 'skateshoes',
component: SkateShoes
},
//more children routes
The issue is that if I manually remove the cookie from my browser and got to /shoes/skateshoes I dont get redirected to the login page.
To get redirected, I have to edit the skateshoes children route like so
{
path: ':skateshoes',
name: 'skateshoes',
component: SkateShoes,
beforeEnter: (to, from, next) => {
if (store.state.login.quad_token == null) {
next('/login');
}
next();
}
},
I thought that putting beforeEnter in the parent will also work for all the children. Apparently this does not work , at least for me.
How do I make it work? Thanks
You should use beforeEach guard instead of beforeEnter.
beforeEnter is a per route guard, it doesn't apply for children.
You can use router's meta combine with beforeEach to add conditional logic.
yes it wouldn't work like that, because 'beforeEnter' guards is per-route guard.
If you want to use something global , then you can use beforeEach
Here you can read , how to implement it in your case : https://router.vuejs.org/guide/advanced/navigation-guards.html
Hope, this could helps you :)

How to use vue-router to redirect to 404 page with invalid URL parameter

I use vue-router to navigate the user pages by their user id.
And the router.js looks like as follows
export default new Router({
mode: 'history',
base: process.env.BASE_URL,
routes: [
{
path: '/user/:id',
name: 'user',
component: () =>
import(/* webpackChunkName: "user" */ './views/User.vue'),
props: true
},
{
path: '/404',
name: '404',
component: () => import('./views/404.vue'),
},
]
})
If someone go to the URL of /user/some-invalid-id, how do I redirect it to the 404 page?
In my app, all user data is loaded at the App.js' breforecreate(), and internally the User view is accessed as follows for existing users
<router-link :to="{name: 'user', params:{id: u.pk}}" >
<a> {{u.first_name}} {{u.last_name}} </a>
</router-link>
I know it's possible to redirect programmatically with a push function call. But I don't know where this code should be used.
this.$router.push('/404')
In the User.vue view page, I use a vuex getter called userByID to retrieve data.
userByID: (state) => id => {
return state.users.find(u => (u.pk == id))
}
Should router.push('/404') happen in userByID or its caller? How do we deal with the template rendering with undefined user object?
I think you want to use 'Navigation Guards`, specifically a beforeEnter hook in your /user/:id route.
Something sort of like this (not tested; just directional):
routes: [
{
path: '/user/:id',
name: 'user',
component: () =>
import(/* webpackChunkName: "user" */ './views/User.vue'),
props: true,
beforeEnter: (to, from, next) => {
if (!userById($route.params.id)) {
next('/404');
}
else {
next();
}
}
}
},
{
path: '/404',
name: '404',
component: () => import('./views/404.vue'),
},
]
Note that you'll need to be able to determine if the user is valid without invoking the User.vue component.
You can also implement a beforeRouteEnter hook on User.vue directly, though you'll not be able to call other User.vue methods there as the component won't yet be mounted.
More on navigation guards: https://router.vuejs.org/guide/advanced/navigation-guards.html#global-guards
Given your userById method is accessing the store, I found this post that might help you access the store in your beforeEnter method: How to access async store data in vue-router for usage in beforeEnter hook?

Vuejs Display a router name in Component

How can I display a router name in a component ?
Example:
const routes = [
{ path: '/documents', component: Documents, name:"Documents" ,props:true},
{ path: '/queries', component: Queries, name:"Queries", props:true}
]
I want to display the name property as a title in the component. Is this possible? how?
props:true will convert path parameters to properties:
{ path: '/documents/:name', component: Documents, name:"Documents", props:true},
You can use an object instead of true and then send in a string.
{ path: '/documents', component: Documents, name:"Documents", props:{ name:'Documents'}},
In your component, register the property
props: { name:String }
And then use it in a template like this:
<div>{{name}}</div>
You can also refer to the route name using the components $route object
<div>{{$route.name}}</div>
To specify title to a component you can use router's meta property, Link
const routes = [
{
path: '/documents',
component: Documents,
name:"Documents" ,
props:true,
meta: {
title: 'Documents'
}
},
{
path: '/queries',
component: Queries,
name:"Queries",
props:true,
meta: {
title: 'Queries'
}
}
]
In main.js,
import router from '#/routes'
router.beforeEach((to, from, next) => {
document.title = `Currently at - ${to.meta.title}`
next()
})