Redirect to specific url in case of wrong url in vuejs - vuejs2

I have two separate routing files where I am importing the component and defining their routing in each of its file and using it in index.js file. Here are my files code:
//router1.js
import Layout1 from 'Layouts/Panel.vue';
const Users = () => import('Views/Users.vue');
const Reports = () => import('Views/Reports.vue');
export default {
path: '/layout1',
component: Layout1,
redirect:'/layout1/reports',
children:[
{
path: 'reports',
component: Reports,
name:'Reports'
},
{
path: 'users',
component: Users,
name:'Users'
}
]
}
//router2.js
import Layout2 from 'Layout/Panel2';
const Demo1 = () => import('Views/Demo1');
const Demo2 = () => import('Views/Demo2');
export default {
path: '/',
component: Layout2,
redirect:'/demo1',
children:[
{
path: '/demo1',
component: Demo1
},
{
path: '/demo2',
component: Demo2
}
]
}
// index.js
import Vue from 'vue'
import Router from 'vue-router'
import router1 from './router1';
import router2 from './router2';
const NotFound = () => import('Views/NotFound.vue');
Vue.use(Router)
export default new Router({
mode: 'history',
routes: [
router1,
router2,
{
path: '*',
component: NotFound,
name:'NotFound',
},
]
})
Now, I want to redirect to specific url i.e "not-found" in case of wrong URL. In "NotFound" component I am adding below line of code in mounted lifecycle hook which redirects to URL "not-found".
this.$router.replace({ path: 'not-found' });
But if URL is having parameters or query string it will append to it. For e.g- http://localhost:8080/home/not-found
What I want is that it only shows http://localhost:8080/not-found How should I achieve this. Please help. Thanks!

try this in your mounted function. worked on my side.
this.$router.push({path: '/not-found'})

Related

exclude a path from vuex-oidc in vue router

I'm using below code to create my vue app routes and vuex-oidc vuexOidcCreateRouterMiddleware to protect them.
My routes are not only in this file. I'm using axios in App.vue to get other routes from an api endpoint and add them to routes using this.$router.addRoute()
When these extra routes are loaded beforeEach applied vuex-oidc to all routes.
Up to this point all works perfectly.
My problem is
I need to exclude "Welcome" route so vuex-oidc will not be applied to it. So it will be accessible to all visitors not only logged-in users.
How can i edit following line to exclude Welcome route?
router.beforeEach(vuexOidcCreateRouterMiddleware(store, 'oidcStore'))
or any other solution.
Thanks
import { createRouter, createWebHistory } from 'vue-router'
import { vuexOidcCreateRouterMiddleware } from 'vuex-oidc'
import store from '#/store'
const routes = [
{
path: process.env.BASE_URL + 'oidc-callback',
name: 'OidcCallback',
component: () => import(/* webpackChunkName: "OidcCallback" */ '../views/OidcCallback.vue')
},
{
path: process.env.BASE_URL + 'profile',
name: 'Profile',
component: () => import('../views/Profile.vue'),
},
{
path: process.env.BASE_URL + 'oidc-silent-renew',
name: 'OidcSilentRenew',
component: () => import('../views/OidcSilentRenew.vue'),
},
{
path: process.env.BASE_URL + 'welcome',
name: 'Welcome',
component: () => import('../views/Welcome.vue'),
},
]
const router = createRouter({
base: '/vue3/',
history: createWebHistory(),
routes
})
router.beforeEach(vuexOidcCreateRouterMiddleware(store, 'oidcStore'))
export default router
Seems I was overlooking. Solution is very simple. Just add isPublic and set it to true under meta in route
const routes = [
...
{
path: process.env.BASE_URL + 'welcome',
name: 'Welcome',
component: () => import('../views/Welcome.vue'),
meta: {
isPublic: true
}
},
...
]

Vue router - navigation guard is skipped when using router.push()

I have a Vue SPA with i18n and some views that require authentication via navigation guard.
When i am not authenticated and go to url via my browser:
examplepage.com/en/lockedpage
i get redirected to:
examplepage.com/en/login
which is good, however when i click a button that runs:
#click="$router.push(`/${$i18n.locale}/lockedpage`)"
i get in to the page even if i am not authenticated.
I want to get redirected to the login page if not authenticated
this is my router.js:
import Vue from 'vue';
import Router from 'vue-router';
import Home2 from './views/Home2.vue';
import Login from './views/Login.vue';
import Register from './views/Register.vue';
import ErrorLanding from './views/ErrorLanding.vue'
import Root from "./Root"
import i18n, { loadLocaleMessagesAsync } from "#/i18n"
import {
setDocumentLang
} from "#/util/i18n/document"
Vue.use(Router);
const { locale } = i18n
export const router = new Router({
mode: 'history',
base: '/',
routes: [
{
path: '/',
redirect: locale
},
{
path: "/:locale",
component: Root,
children: [
{
name: 'Home',
path: '',
component: Home2,
},
{
name: 'Home2',
path: '/',
component: Home2,
},
{
name: 'Login',
path: 'login',
component: Login,
},
{
path: 'register',
component: Register,
},
{
path: 'lockedpage',
name: 'lockedpage',
webpackChunkName: "lockedpage",
meta: {authRequired: true},
component: () => import('./views/LockedPage.vue')
},
{
path: '*',
component: ErrorLanding,
name: 'NotFound'
}
]
}
],
router.beforeEach((to, from, next) => {
if (to.params.locale === from.params.locale) {
next()
return
}
const { locale } = to.params
loadLocaleMessagesAsync(locale).then(() => {
setDocumentLang(locale)
const publicPages = [ `/`, `/${locale}`, `/${locale}/`];
const authRequired = !publicPages.includes(to.path);
const loggedIn = localStorage.getItem('user');
const redirect = to.path;
if (authRequired && loggedIn === null) {
if(to.meta.authRequired === false) {
next();
}
else
next({ name: 'Login', query: { redirect: redirect } });
} else {
next();
}
})
next()
});
Why does my navigationguard skip when using router.push() ?
This issue started after adding i18n, with localeredirect. so all routes comes after a locale for example: /en/.../
As Estus points out in the comments, the issue is that the first thing you're checking for is if the locales match, and if they do you're calling next() and sending the user to the page.
As outlined here:
Make sure that the next function is called exactly once in any given pass through the navigation guard. It can appear more than once, but only if the logical paths have no overlap, otherwise the hook will never be resolved or produce errors.
If you need to keep the locale check between the to and from pages, you could do something like:
if (to.params.locale === from.params.locale && loggedIn) {
next()
return
}
which will check if the loggedIn variable is truthy before pushing the user to the page they're trying to navigate to.
I believe just removing the if statement that checks if the locales match would also work.

Accessing to store in the router

I would like to check in my Vuex store whether a user has the 'admin' role before entering the /dashboard route. But I can't properly access data from store.getters.
I use Quasar (Vue.js) and Vuex + Typescript.
In the routes.ts file, on the beforeEnter() function, I can access getters from the store with a console.log(store.myStore.getters). Here I see userInfos inside:
I don't understand why I only get {} and not {...} (Note that if I click on it, I see its contents).
But if I call console.log(store.myStore.getters.userInfos), I don't see the data:
Here is index.ts (router):
import { route } from 'quasar/wrappers'
import VueRouter from 'vue-router'
import { Store } from 'vuex'
import { StateInterface } from '../store'
import routes from './routes'
export default route<Store<StateInterface>>(function ({ Vue }) {
Vue.use(VueRouter)
const Router = new VueRouter({
scrollBehavior: () => ({ x: 0, y: 0 }),
routes,
mode: process.env.VUE_ROUTER_MODE,
base: process.env.VUE_ROUTER_BASE
})
return Router
})
Here is routes.ts (router):
import { RouteConfig } from 'vue-router'
const routes: RouteConfig[] = [
{
path: '/',
component: () => import('layouts/Login.vue'),
children: [
{ path: '', component: () => import('pages/Index.vue') },
{ path: '/inscription', component: () => import('pages/SignUp.vue') },
{ path: '/connexion', component: () => import('pages/SignInPage.vue') }
]
},
{
path: '/main',
component: () => import('layouts/MainLayout.vue'),
children: [
{ path: '', component: () => import('pages/Index.vue') },
{ path: '/dashboard', component: () => import('pages/DashboardB2B.vue'),
beforeEnter: (to, from, next) => {
const store = require('../store')
console.log("before enter")
console.log(store.myStore.getters)
return next();
}, },
{
path: '/ajouter-un-referentiel',
component: () => import('pages/ReferentielMetier.vue')
},
{
path: '/init',
component: () => import('components/bot/BotSkeleton.vue')
}
]
},
{
path: '/bot',
component: () => import('layouts/Bot.vue'),
children: [
{
path: '/ajouter-un-referentiel',
component: () => import('pages/ReferentielMetier.vue')
},
{
path: '/init',
component: () => import('components/bot/BotSkeleton.vue')
}
]
},
// Always leave this as last one,
// but you can also remove it
{
path: '*',
component: () => import('pages/Error404.vue')
}
]
export default routes
And here is index.ts with the store (Vuex):
import Vue from 'vue'
import { store } from 'quasar/wrappers'
import Vuex from 'vuex'
Vue.use(Vuex)
import matching from './modules/matching'
import orga from './modules/organigrame'
import user from './modules/user'
export interface StateInterface {
example: unknown
}
let myStore: any
export default store(function({ Vue }) {
Vue.use(Vuex)
const Store = new Vuex.Store<StateInterface>({
modules: {
matching,
orga,
user
},
// enable strict mode (adds overhead!)
// for dev mode only
strict: !!process.env.DEBUGGING
})
myStore = Store
return Store
})
export {myStore}
EDIT: Looks like my console.log runs before the getters are loaded, because when I check out Vue developer tools, I see everything. How can I check the store if the store itself doesn't load before the beforeEnter function?
please try like this
store.myStore.getters["userInfos"]
I'm having exact issue, even if i use async/await :S
try this
router.beforeEach(async(to, from, next) => {
const userInfo = await store.getters.userInfos;
console.log(userInfo);
});

How to correct, Maximum call stack size exceeded, vue-router?

Good day.
I have the following error:
[vue-router] uncaught error during route navigation:
vue-router.esm.js:1897 RangeError: Maximum call stack size exceeded
at String.replace (<anonymous>)
at resolvePath (vue-router.esm.js:597)
at normalizeLocation (vue-router.esm.js:1297)
at Object.match (vue-router.esm.js:1341)
at VueRouter.match (vue-router.esm.js:2461)
at HashHistory.transitionTo (vue-router.esm.js:1865)
at HashHistory.push (vue-router.esm.js:2267)
at eval (vue-router.esm.js:1952)
at router.beforeEach (index.js:116)
at iterator (vue-router.esm.js:1935)
According to the error it is in my file of routes, which I have it in the following way:
import Vue from 'vue'
import Router from 'vue-router'
import Home from '../components/Home'
import Vehiculos from '../components/Vehiculos'
import Perfil from '../components/Perfil'
import Login from '../components/Login'
import TutorialIntroduccion from '../components/TutorialIntroduccion'
import Politicas from '../components/Politicas'
import Parqueo from '../components/Parqueo'
import Politicas from '../components/Politicas'
import Historial from '../components/Historial'
import firebase from 'firebase'
Vue.use(Router)
let tutorialVisto = localStorage.getItem("Tutorial");
const router = new Router({
routes: [
{
path: '*',
redirect: '/login'
},
{
path: '/',
redirect: '/tutorial'
},
{
path: '/tutorial',
name: 'tutorial',
component: TutorialIntroduccion,
meta: {
tutorialVisto: tutorialVisto,
autentificado: false
},
beforeEnter: (to, from, next) => {
let tutorialVisto = to.matched.some(record=>record.meta.tutorialVisto);
if (tutorialVisto)next('login');
else next();
}
},
{
path: '/login',
name: 'Login',
component: Login
},
{
path: '/home',
name: 'home',
component: Home,
meta: {
autentificado: true
}
},
{
path: '/parqueo/:id',
name: 'parqueo',
component: Parqueo,
meta: {
autentificado: true
}
},
{
path: '/vehiculos',
name: 'vehiculos',
component: Vehiculos,
meta: {
autentificado: true
}
},
{
path: '/perfil',
name: 'perfil',
component: Perfil,
meta: {
autentificado: true
}
},
{
path: '/politicas',
name: 'politicas',
component: Politicas,
meta: {
autentificado: true
},
},
{
path: '/historial',
name: 'historial',
component: Historial,
meta:{
autentificado: true
}
}
]
})
router.beforeEach((to, from, next) => {
let usuario = firebase.auth().currentUser; //Debe ser otra Promesa si esta autenticado o no.
let autorizacion = to.matched.some(record=>record.meta.autentificado);
let tutorialVisto = to.matched.some(record=>record.meta.tutorialVisto);
if (autorizacion && !usuario) {
next('login');
}
else if (!autorizacion && usuario) {
next('home');
}
else{
next();
}
})
export default router;
The problem arises when I am in the parking lot view and then when I log in, it does not redirect me to the vita login, but it gives me that error and stays in the same view, although it does close the firebase session. If I am in any of the other views, for example, vehicles, profile or main and then I give in closing session does not generate me error.
The session closing code is the following:
linkto(pathname) {
this.$router.push({ path: pathname })
if(pathname=="/login") {
firebase.auth().signOut().then(() => this.$router.replace('login'))
}
},
According to vue router's docs:
{
// will match everything
path: '*'
}
It is usually used to redirect to a 404 page not another route. In your case, you are calling a new route /login and it matches in * as well, which causes the loop and the Maximum call stack size exceeded.
You have multiple spelling mistakes in your next handlers. These calls accept the name of a route, and if you pass it a name of an route that does not exists, it will behave unspecified.
From what I can see is that you are trying to redirect to login, while you actually called the route Login
It happened to me too.
So after my investigation I have found if you are using Vuejs v. 2.* you have to use the vue-router of v. 2.* (not version 3).
Please see the following examaple:
package.json:
"dependencies": {
"vue": "^2.6.11",
"vue-router": "^2.8.1"
router.ts:
import Vue from "vue";
import VueRouter, { RouteConfig } from "vue-router";
import { Component } from "vue-router/types/router";
import Home from "#/views/Home.vue";
import NotFound from "#/views/NotFound.vue";
import MyPage from "#/views/MyPage.vue";
Vue.use(VueRouter);
const routes: Array<RouteConfig> = [
{
path: "/",
name: "Home",
component: Home as Component
},
{
path: "/my-page",
name: "MyPage",
component: MyPage as Component
},
{
// will match everything else
path: '*',
name: "NotFound",
component: NotFound as Component
}
];
const router = new VueRouter({
mode: "history",
routes
});
export default router;

Route config "component" for path: / cannot be a string id

I am building routes into my website using vue-router, I am attempting to setup my route file the same way coreui does it. I am currently receiving the error "[vue-router] route config component" for path: / cannot be a string id. Use an actual component instead.
./src/router/index.js
import Vue from 'vue';
import Router from 'vue-router';
// Containers
const DefaultContainer = '../containers/DefaultContainer';
// Componenets
// const Navbar = '../components/Navbar';
// Views
const Home = '../views/Home';
const PageNotFound = '../views/404';
// Routes
Vue.use(Router)
export default new Router ({
mode: 'hash',
routes: [
{
path: '/',
redirect: '/home',
name: 'Home | Portfolio | Tom Dickson',
component: DefaultContainer,
children: [
{
path: 'home',
name: 'Home | Portfolio | Tom Dickson',
component: Home
}
]
},
{
path: '*',
component: PageNotFound
}
]
})
Well... Came back to it and was right in front of me:
Changed
// Containers
const DefaultContainer = '../containers/DefaultContainer';
To
// Containers
const DefaultContainer = () => import('../containers/DefaultContainer');
Then updated the rest of my views...