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

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'),
},

Related

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 :)

Redirect all links containing # hash sign

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();
});

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?

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 }
]
});

VueRouter omitting the forward slash before the # in non-history mode

i'm trying to use VueRouter 2.2.1 in my Laravel application and for some reason my URL's (although working) show the # symbol in a weird way
http://myapp.dev/admin#/
Instead of
http://myapp.dev/admin/#/
As i would normally expect...
This is my VueRouter configuration
const Router = new VueRouter({
routes: [
{
path: '/',
component: App,
children: [
{
path: 'dashboard',
name: 'dashboard',
component: Dashboard
}
]
}
]
});
And on the PHP side of things i'm just defining a catch all route for the /admin section of the Application
// Catch-all Route, sends GET requests to VueRouter //
Route::get('{all?}', function() {
return view('index');
})->where(['all' => '(.*)'])->name('catchall');
Like this, is there anything i'm doing wrong? It is working but it just kinda bugs me that the # just floats there.
You have to enable history mode, as stated here, I dont see that in your vue-router config.
const Router = new VueRouter({
mode: 'history',
routes: [
{
path: '/',
component: App,
children: [
{
path: 'dashboard',
name: 'dashboard',
component: Dashboard
}
]
}
]
});
You have to do it on server side, just redirect the route to one ended with '/'
As in laravel:
Route::get('{all?}', function() {
return view('index');
})->where(['all' => '^/admin\/$'])->name('catchall');
now just visit /admin/#/