How to hold URL query params in Vue with Vue-Router - javascript

I am doing a project in Vue with Vue-Router . in my project ,i have a param named 'adtag' , which must be in the url query params , is there any simple way to hold this param ,no mater how router goes.
for example , I have three pages:
localhost/index
localhost/list
localhost/detail?id=11
page change using vue-router <router-link :to="{name:'Detail',query:{id:item.id}}"></router-link>
if I opened first page localhost/index?adtag=123 with adtag,page will changes with param 'adtag'
localhost/index?adtag=123
localhost/list?adtag=123
localhost/detail?adtag=123&id=11

With a default Vue 2.x installation, the router file is located src/router/index.js
I was able to then check if I needed to modify the request and add in any missing query params (modifying the to var apparently has no effect), and then call a "redirect" of next( .. new rout.. ).
Downside: Doubles the route calls, because essentially it redirects
Upside: It works, and the query preserving logic is in one place.
One caveat: On page load, the router fires and the "from" is a very empty route (even excluding the query params that were in the URL). Therefor I setup that if statement to verify the need to place the query param in place.
import Vue from 'vue'
import Router from 'vue-router'
// ... All your other components
Vue.use(Router)
const router = new Router({
mode: 'history',
routes: [
{
path: '/',
name: 'Dashboard',
component: Dashboard
},
// ... All your other routes
]
})
router.beforeEach((to, from, next) => {
if (from.query.token && !to.query.token) {
if (to.path === from.path) {
// console.log('Identical routes detected')
return // This is a no-no via the documentation, but a bug in routing to identical routes strips query params, and this prevents that
}
next({path: to.path, query: {token: from.query.token}})
}
next()
})
export default router

As this is still an issue, I would even recommend using next(false) instead of returning.
if (from.query.foo && !to.query.foo) {
if (from.path === to.path) {
next(false);
} else {
next({
path: to.path,
query: { ...to.query, foo: from.query.foo },
});
}
} else {
next();
}
For reference, the same issue from the github repository: https://github.com/vuejs/vue-router/issues/1900#issuecomment-346531301.

Related

Page with the authRequired meta still gets shown for a split second even when no one is logged in on Firebase

I'm new to Vue / web development, ever since I started i've had a good amount of fun but now i'm stuck.
Currently I am creating an admin dashboard with Firebase authentication. Everything seems to work like it should but there is one thing that I still don't understand.
In the Vue Router I have all the different routes set up and the dashboard is inaccessible (if not logged in to Firebase).
This is my Router Guard:
const routes = [
{
path: "/",
name: "Home",
component: Home,
},
{
path: "/register",
name: "Register",
component: Register,
},
{
path: "/login",
name: "Login",
component: Login,
},
{
path: "/dashboard",
name: "Dashboard",
component: Dashboard,
meta: {
requiresAuth: true,
},
},
];
router.beforeEach((to) => {
//If route requires authentication
if (to.matched.some((rec) => rec.meta.requiresAuth)) {
//Check firebase user
auth.onAuthStateChanged((user) => {
console.log(user);
//If the user object does not exist then redirect to the /Login page
if (!user) {
router.push("/login");
}
});
}
});
If I now try to open localhost:8080/dashboard it shows the dashboard for a split second and then hops to the /login page.
If also tried it with next({name: 'Login'}) but for some reason I keep getting white pages when I use next().
Hope someone can help me.
Thanks :)
The problem is that instead of checking for a logged-in user you are adding an "event listener" auth.onAuthStateChanged.. it fires async when the authentication state changes. However you need a sync check here. The best would be to use vuex and store your user in a global state. Though if you don't use vuex at all and you need your user only here, then probably a "local" user var in the router would also work.. something like this:
let user = null
auth.onAuthStateChanged(u => {
console.log(u)
if (u) {
user = u
} else {
user = null
}
})
router.beforeEach(to => {
if (to.matched.some(rec => rec.meta.requiresAuth)) {
//Check firebase user
if (!user) {
router.push("/login");
}
}
})
It's just a concept, but it should work.. let me know :)

router push doesn't work in vuejs when i want to pass params

When I want to use programmatic navigation by vue-router package it works, but when I want to pass params to a component with router.push methods, it doesn't work at all. Does anybody have a solution?
My code here:
import VueRouter from 'vue-router'
import routes from './routes';
const router = new VueRouter({routes});
Vue.use(VueRouter);
and the push code:
router.push({ name: 'reportArchive', params: {token: token} });
My route config:
{ path: '/reportArchive', name: 'reportArchive', component: reportArchive },
If you really want to pass param, you will need to set the route to accept param, just like below :
{ path: '/reportArchive/:token', name: 'reportArchive', component: reportArchive },
This is as per Eldar's answer above, but if you want to pass url query parameters, you need to use query instead of params in the code, for example :
router.push({ name: 'reportArchive', query: {token: token} });
Your route definition doesn't accept a paramater. You should define your route as below :
{ path: '/reportArchive/:token', name: 'reportArchive', component: reportArchive },

Advanced Vue router guards

So, I have my routers set up like this:
const routes = [
{
path: '/',
name: 'HomePage',
component: HomePage,
beforeEnter: checkAuth,
meta: {
requiresAuth: false,
showSidebar: false
}
},
{
path: '/feed',
name: 'FeedPage',
component: FeedPage,
beforeEnter: checkAuth,
beforeRouteEnter: ((to, from, next) => {
console.log(from)
}),
meta: {
requiresAuth: true,
showSidebar: true
}
},
{
path: '/faq',
name: 'FAQPage',
component: FAQPage,
beforeEnter: checkAuth,
meta: {
requiresAuth: true,
showSidebar: true
}
},
}
]
So checkAuth is a function that basically checks wether the user is authenticated before Entering that route (using google auth), which works perfectly. But I also want to use beforeRouteEnter to check whether the user's designation is allowed in that route AFTER authentication. I have the designation stored in the Vuex store.
How can I use this keyword such that I can use the plugins?
And also, what is the proper way to use beforeRouteEnter?
Based on the Vue Router documentations, The beforeRouteEnter guard does NOT have access to this, because the guard is called before the navigation is confirmed, thus the new entering component has not even been created yet.
However, you can access the instance by passing a callback to next. The callback will be called when the navigation is confirmed, and the component instance will be passed to the callback as the argument:
beforeRouteEnter (to, from, next) {
next(vm => {
// access to component instance via `vm`
})
}
Also there are beforeRouteUpdate & beforeRouteLeave you might want use as well based on your needs, for these this is available ( but passing callback is not supported on these two )
beforeEnterand beforeRouteEnter are both guards with the same goal, the difference is where to use it.
beforeEnter is a guard you can define on a route's configuration object. https://router.vuejs.org/guide/advanced/navigation-guards.html#per-route-guard
beforeRouteEnter is a guard you define on your component.
https://router.vuejs.org/guide/advanced/navigation-guards.html#in-component-guards
Either way if you want to access you Vuex Store you should import it.
This could be an Example of your FeedPage component usign beforeRouteEnter
<script>
import Store from '../vuexstore.js'
export default{
beforeRouteEnter(to,from,next){
if(Store.state.isAllowed){
next()
} else {
next(false)
}
}
</script>
Don't forget to use next() to continue the navigation after the validation.

angular route path with parameters separated with &

This type of path is not working:
{ path: 'account/finalize?user=:user&token=:token', component: MyComponent }
I get route not found error when I access http://localhost:4200/account/finalize?user=devanshu&token=122323
But this is working:
{ path: 'account/finalize/:school/:token', component: MyComponent }
So, I can access http://localhost:4200/account/finalize/devanshu/122323
What is the problem here? Why is there an error in the first case?
you can use
path: 'account/finalize'
and send user and token as query Params when navigating
this.router.navigate(['/account/finalize'], { queryParams: { user: 'user', token: 'your token' } });
I think you do not need to pass these parameters:
user=:user&token=:token
You can get these parameters in the req.body
And if there is any particular component then you have to place the condition within the function.

How to redirect to a different url inside the vue-router beforeRouteEnter hook?

I am building an admin page with Vue.js 2 and I want to prevent unauthenticated users from accessing the /admin route and redirect them to /login. For that I have used the In-Component Guard beforeRouteEnter in the Admin component like follows
...
beforeRouteEnter(to, from, next) {
if(userNotLogedIn) {
this.$router.push('/login');
}
}
The problem here is that this is not defined in beforeRouteEnter hook. So what's the proper way to access $router and redirect to a different url in this case ?
The documentation states that:
The beforeRouteEnter guard does NOT have access to this, because the
guard is called before the navigation is confirmed, thus the new
entering component has not even been created yet.
You can redirect to another page by calling next like this:
beforeRouteEnter(to, from, next) {
if(userNotLogedIn) {
next('/login');
}
}
Here is another way to accomplish the same result: So instead of using beforeRouteEnter on each protected route, you could define protected routes in your router configuration using a meta property, then use beforeEach hook on all the routes and check for protected routes and redirect to login page when needed:
let router = new Router({
mode: 'history',
routes: [
{
path: '/profile',
name: 'Profile',
component: Profile,
meta: {
auth: true // A protected route
},
},
{
path: '/login',
name: 'Login',
component: Login, // Unprotected route
},
]
})
/* Use this hook on all the routes that need to be protected
instead of beforeRouteEnter on each one explicitly */
router.beforeEach((to, from, next) => {
if (to.meta.auth && userNotLoggedIn) {
next('/login')
}
else {
next()
}
})
// Your Vue instance
new Vue({
el: '#app',
router,
// ...
})

Categories

Resources