Redirect all links containing # hash sign - vue.js

After changing Vue router mode from hash to history, old links do not redirect the user to the new URL.
Some still use the old link.
const router = new Router({
mode: 'history',
routes: [
{
path: '/#/',
name: 'Home',
component: Home
},
{
path: '/',
name: 'Home',
component: Home
},
]
})
I need to redirect all existing URL links to URL without hash.

You can replace hash in beforeEach hook:
router.beforeEach((to, from, next) => {
if (to.fullPath.substr(0,2) === "/#") {
const path = to.fullPath.substr(2);
next(path);
return;
}
next();
});

Related

vue router - redirect after successfull authentication

I have a vue app which uses the vue router. I implemented an authentication system for the login routes. How do I get it to redirect automatically to the route the user initially wanted to visit after login was successfull?
This is my code
import Vue from "vue";
import VueRouter, { RouteConfig } from "vue-router";
import Home from "../views/Home.vue";
import Collections from "../views/Collections.vue";
import Login from "../views/Login.vue";
import store from "../store/index";
Vue.use(VueRouter);
const routes: Array<RouteConfig> = [
{
path: "/login",
name: "Login",
component: Login,
},
{
path: "/",
name: "Home",
component: Home,
},
{
path: "/collections",
name: "Collections",
component: Collections,
//meta: { requiresAuth: true }
},
];
const router = new VueRouter({
mode: "history",
base: process.env.BASE_URL,
routes,
});
router.beforeEach((to, from, next) => {
if (!store.getters.isAuthenticated && to.name !== "Login") {
next("/login");
} else {
next();
}
});
export default router;
Instead of just calling next('/login'), you can additionally pass the route that users want to visit as a query parameter, like this:
next({
path: '/login',
query: {
redirect: to.fullPath,
}
})
Then, in the login page, after the successful authentication, you can call
this.$router.replace(this.$route.query.redirect || '/');
It will redirect users to the page they initially want to visit, or to home if there is no information about redirection.
Use cookie storage
this.cookieUrl = this.$route.query.redirecturl
if (this.cookieUrl) {
cookieStorage.setItem('redirecturl', this.cookieUrl, false, 2000000)
}
and after login check cookie
if (cookieStorage.getItem('redirecturl')) {
this.$router.push({
path: cookieStorage.getItem('redirecturl')
})
cookieStorage.removeItem('redirecturl')
The plain and simple approach which could work in that case is simply redirecting back to previous route after successful login.
$router.go(-1)
Your best option is to initially redirect the person to the login page with a parameter that specifies the original page. Something like:
if(!loggedIn) {
// If not authenticated, add a path where to redirect after login.
this.$router.push({ name: 'login', query: { source_path: '/current_route' }});
}
(you can optionally use this.$route.query.page in place of an explicit /current_route string).
Then in the login page have a method that uses the parameter if set, or falls back to the homepage:
this.$router.push(this.$route.query.source_path || '/')

Vue router does not route to my pages - It returns cannot get /home

My routes array looks like this
const routes = [
{
path: '/',
component: () => import('layouts/MainLayout.vue'),
children: [{ path: '', component: () => import('pages/Index.vue') }],
},
{
path: 'home',
component: () => import('pages/Home.vue'),
},
// Always leave this as last one,
// but you can also remove it
{
path: '*',
component: () => import('pages/Error404.vue'),
},
];
But when I navigate to home it says cannot GET /home.
I'm using quasar btw, if that helps.
History mode
first make sure you are using history mode so you can access routes like /home directly . if history mode is not activated you will have a # thats hash_mode wich is default in vuejs
vue router example
const router = new VueRouter({
mode: 'history',
routes: [...]
})
Only frontend Routes
second in case of an spa that is loaded from a route like laravel make sure your backend is not redirecting users to any other page than the root / and all the routing should be handeled only buy your frontend .
laravel web.php example
Route::get('{path}', function () {
return view('app');
})->where('path', '.*');
Not an spa ?
if this is not an spa then you need to use hash mode ( remove history mode) , and access vue routes using the hashed url syntax
example hash urls
https://myspa.com/#/ for the MainLayout.vue
https://myspa.com/#/home for the pages/Index.vue
Try to use '/home' in your home route
{
path: '/home',
component: () => import('pages/Home.vue'),
},

Vue beforeEach() doesn't redirect to the desired page

I'm trying to redirect/continue to a certain page using vue router, After a user signs up with email and password they should be redirected to another page but the home page just gets reloaded.
I'm not implementing login at the moment, Just the signup part. Every example that I follow works fine in redirecting with just "next()"
import Vue from "vue";
import VueRouter from "vue-router";
import Home from "../views/Home.vue";
import Admin from "../views/Admin.vue";
import Overview from "../views/Overview.vue";
import Products from "../views/Products.vue";
import Orders from "../views/Orders.vue";
import { fb } from "../firebase";
Vue.use(VueRouter);
// The 'name' property hasn't been utilized yet
const routes = [
{
path: "/",
name: "Home",
component: Home
},
{
path: "/admin",
name: "admin",
component: Admin,
// By adding 'requiresAuth' we ensure this route/page and it's children will not be
// accessable by someone who is not authenticated
meta:{ requiresAuth: true },
children:[
{
// Don't put the '/' here
path: "overview",
name: "overview",
component: Overview
},
{
// Don't put the '/' here
path: "products",
name: "products",
component: Products
},
{
// Don't put the '/' here
path: "orders",
name: "orders",
component: Orders
}
]
},
{
path: "/about",
name: "About",
// route level code-splitting
// this generates a separate chunk (about.[hash].js) for this route
// which is lazy-loaded when the route is visited.
component: () =>
import(/* webpackChunkName: "about" */ "../views/About.vue")
}
];
const router = new VueRouter({
mode: "history",
base: process.env.BASE_URL,
routes
});
// ============= This is the method in question ==============
router.beforeEach((to, from, next) => {
const requiresAuth = to.matched.some(x => x.meta.requiresAuth);
const currentUser = fb.auth().currentUser;
// This condition always passes, Even after the user is registered, So it always reloads
// the home page
if (requiresAuth && !currentUser) {
next('/');
// This never runs
} else {
next();
}
});
export default router;

How to not be able to access manually /login after you logged in - VueJS?

I'm learning VueJS from an Udemy course. In the module about authentication, the instructor didn't make the whole process, so I had to try it by my self for 2 days but I succeeded 90%.
The backend is on firebase, so after login with correct data, I get back a token that I send it to local storage.
With the code that I make it, you can't see the dashboard if you are not authenticated(even you try the route manually), but what I don't like is that you can see the login page after you are authenticated(if you type /signin).
This last part is not normal to be. So if you are authenticated, when you try manually to go to /signin, you can.
In the router.js:
const routes = new VueRouter({
mode: 'history',
routes: [
{ path: '/', component: WelcomePage },
{ path: '/signup', component: SignupPage },
{ path: '/signin', component: SigninPage },
{ path: '/dashboard', component: DashboardPage}
]
});
routes.beforeEach((to, from, next) => {
// redirect to login page if not logged in and trying to access a restricted page
const publicPages = ['/signin', '/signup'];
const authRequired = !publicPages.includes(to.path);
const loggedIn = localStorage.getItem('token');
console.log(loggedIn);
if (authRequired && !loggedIn) {
return next('/signin');
}
next();
});
And in store.js, inside login action:
if (localStorage.getItem('token')) {
router.replace("/dashboard");
}
Any idea what to do to /login and /register routes after login so to not be able to see them, even you manually try these routes?
If the user will try manually /signin or /signup, I want to be redirected to /dashboard.
In my vue application I just use the router.beforeEach method with meta data plus the state of my token which I pull from my store.
router.beforeEach((to, from, next) => {
if (to.matched.some(record => record.meta.requiresAuth)) {
var token = store.getters.loggedIn;
if (!token ) {
next({
path: '/login',
})
} else {
next()
}
}else if (to.matched.some(record => record.meta.requiresVisitor)) {
if (token) {
next({
path: '/',
})
} else {
next()
}
}
})
It checks each time the route changes.
The requiresVisitor meta is something I placed in my router object
{
// this is can only be viewed if not logged in.
path: '/login',
name: 'login',
component: () => import(/* webpackChunkName: "login" */ './views/Login.vue'),
props: true,
meta: {
requiresVisitor: true,
layout: "landing",
},
},
{
// this can only be viewed if logged in.
path: '/',
name: 'dashboard',
component: () => import(/* webpackChunkName: "dashboard" */ './views/Dashboard.vue'),
props: true,
meta: {
requiresAuth: true,
layout: "default",
},
},
you can read more about route guards Here
theses methods are typically used in the entry point to the app main.js or in your router.js file.
You can add a per-route guard (https://router.vuejs.org/guide/advanced/navigation-guards.html#per-route-guard) to make the logic only run when /signin and /signup is matched, but if you want to keep it in the loop that runs over all routes you're on the right track -- you just need to invert your logic.
So what you want do is to add another if statement, checking if isLoggedIn is true, and that you're trying to access a public page, and in that case redirect the user to the /dashboard route.
if (!authRequired && loggedIn) {
next('/dashboard');
return;
}
Best example of redirection using beforeEach
const routes = [
{
path: "/",
name: "login",
component: Login,
meta:{requiresVisitor: true},
},
{
path: "/dashboard",
name: "dashboard",
component: Dashboard,
meta:{requiresVisitor: false},
}];
const router = new VueRouter({
mode: "history",
base: process.env.BASE_URL,
routes
});
export default router;
//Check the user is loged in If yes then move to next url.If not loged
in so move in else and check the meta and move into next other wise is
redirect my index url
router.beforeEach((to, from, next) => {
const isLogged = JSON.parse(localStorage.getItem('username'));
if (isLogged) next()
else{
if(to.meta.requiresVisitor) next()
else next('/')
}
})

Cannot read query params becouse vue.js is adding #/ to the end of url

I have a one page app in vueJS:
let router = new VueRouter({
routes: [
{ path: '/', component: Dis13HomeComponent },
{ path: '**', component: Dis13HomeComponent }
]
});
In main component in mounted() im getting the url param like this:
this.$route.query.token;
But if I open http://www.myapp.com/app.html?token=s56ds6d5d56f6ef6e it does not read the token parameter, becouse vue is adding #/ to the end of url so it looks like http://www.myapp.com/app.html?token=s56ds6d5d56f6ef6e#/
If I open this format of url: http://www.myapp.com/app.html#/?token=s56ds6d5d56f6ef6e then it works, but this path is forbidden on server.
How could I read the token parameter?
Make your router to work with history mode and you will not have the '#' anymore.
const router = new VueRouter({
mode: 'history', // <------------- HERE
routes: [
{ path: '/', component: Dis13HomeComponent },
{ path: '**', component: Dis13HomeComponent }
]
});