Router-View tag doesn't display content with beforeEach() - vue.js

I have a vue-router that works as designed, but the moment I add the beforeEach() function to it, nothing appears in the <router-view> tags. Even if the beforeEach() function is empty, it still hides the content from the page. I there something else I need to do to make the <router-view> tag and router work with each other even with the beforeEach() function?
Here is the router:
import Vue from 'vue'
import Router from 'vue-router'
import Home from './views/Home.vue'
Vue.use(Router)
const router = new Router({
mode: 'history',
base: process.env.BASE_URL,
routes: [
{
path: '/',
name: 'home',
component: Home,
meta: {
authenticatedRoute: false
}
},
{
path: '/login',
name: 'login',
component: () => import(/* webpackChunkName: "login" */ './views/Login.vue'),
meta: {
authenticatedRoute: true
}
}
]
})
router.beforeEach((to, from, next) => {
// test
})
export default router;
And the <router-view> tag:
<v-content>
<router-view></router-view>
</v-content>

If your beforeEach fails to call next(), the route will not resolve.
With that in mind, a completely minimal beforeEach would be
router.beforeEach((to, from, next) => {
next()
})
From the documentation...
next: Function: this function must be called to resolve the hook.
...
Make sure to always call the next function, otherwise the hook will never be resolved.

Related

Vue routing dynamic

I have a backoffice in Laravel with dynamic routes, however, I don't know how I do this in vue js, that is, create routes dynamically, so that a controller or something like that returns me the correct view!
You could try Vue Router's Dynamic Route matching, passing different values for route parameters: https://router.vuejs.org/guide/essentials/dynamic-matching.html
Small example for you.
Laravel part
Your "web" routes in Laravel
Route::get('/{any}', 'AppController')->where('any', '.*');
Inside invoke controller
public function __invoke()
{
return view('app');
}
In app.blade
#extends('layouts.app')
#section('content')
<div id="app">
<app/>
</div>
#endsection
Vuejs part:
Your router file
import Login from "./views/Login";
import Home from "./views/Home";
import NotFound from "./views/NotFound";
Vue.use(VueRouter);
let router = new VueRouter({
routes: [
{ path: '/login', name: 'login', component: Login },
{ path: "/", name: 'home', component: Home },
{ path: "*", name: '404', component: NotFound }
});
In app.js
import router from './router';
const app = new Vue({
store,
router,
i18n,
el: '#app',
});
All post, put, patch routes should be "api" routes.

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

Vue: beforeEach is not a function

Route change doesn't scroll to top, so Vue creator advises to use navigation guards. In the updated version:
Router.beforeEach(function (to, from, next) {
window.scrollTo(0, 0)
next();
})
Perfect, except it yields this fatal error in my app: ncaught TypeError: vue_router__WEBPACK_IMPORTED_MODULE_1__.default.beforeEach is not a function
Why?
Just in case here's my complete router.js file:
import Vue from 'vue'
import Router from 'vue-router'
import Home from './views/Home.vue'
import PastEvents from './views/PastEvents.vue'
import BasicPage from './views/BasicPage.vue'
Vue.use(Router)
export default new Router({
mode: 'history',
routes: [
{
path: '/',
name: 'home',
component: Home
},
{
path: '/past-events',
name: 'past-events',
component: PastEvents
},
{
path: '/basic-page',
name: 'basic-page',
component: BasicPage
}
]
})
Router.beforeEach(function (to, from, next) {
window.scrollTo(0, 0)
next();
})
You've capitalized Router, that's the class name. What you want to do is add your .beforeEach() to the instance of the router. You'll notice in the documentation that it's always a lowercase router they're adding the guards to.
Currently, you're immediately exporting the instance from the module, so you'll need to first add it to a variable when you create a new Router and then add your .beforeEach() clauses to it before finally exporting it.
const router = new Router({
...
})
router.beforeEach( ... )
export default router

vue-router neither watch route or navigation guards firing

Using vue-router in a single page application with the code below, the watch $route function in not firing when redirecting to mycomponent.
Also the beforeRouteUpdate in mycomponent is also not firing.
How can I detect when a variable has been tagged on to a route during component load?
App.vue
<template>
<router-view></router-view>
</template>
<script>
import Vue from 'vue'
export default {
name: 'app'
}
</script>
index.js
import Vue from 'vue'
import Router from 'vue-router'
import MyView from '#/views/MyView'
Vue.use(Router)
export default new Router({
routes: [
{
path: '/',
redirect: '/home',
name: 'Home',
children: [
{
path: '/mycomponent',
name: 'MyComponent',
component: MyComponentView
},
{
path: '/mycomponent/:id',
component: MyComponentView,
props: true
}
]}]})
mycomponent.vue
<template>
<component :is="activeComponent" :id="id"></component>
</template>
<script>
export default {
name: 'MyComponentView',
components: {
...
},
mounted: function() {
#this logs path in browser
console.log('>>mounted route: ' + this.$route.path)
},
watch: {
'$route': function () {
#this does not fire
console.log('route watcher: ' + this.$route.path)
}
},
beforeRouteUpdate (to, from, next) {
#this does not fire
console.log('>>beforeRouteUpdate')
},
data () {
return {
activeComponent: 'somecomponent'
}
}
}
</script>
component1.vue
...
mounted: function() {
Event.$on('vue-tables.row-click', function(data) {
#this logs correct information in browser
console.log('data.row.id: ' + data.row.id)
router.push({path: 'mycomponent', query: {id: data.row.id}})
})
},
...
It doesn't work because beforeRouteUpdate is in component which is going to reload (Look at Life cycle of Vue). When you change the route, watch & beforeRouteUpdate is terminated and you won't see any results. In this scenario you should provide something like this:
MainRouterView.vue
<template>
<router-view/>
</template>
<script>
name: 'MainRouterView',
beforeRouteUpdate (to, from, next) {
console.log('beforeRouteUpdate')
},
</script>
router.js
export default new Router({
routes: [
{
{
path: '/mycomponent',
name: 'MainRouterView',
component: MainRouterView,
children: [
{
path: '/mycomponent/:id',
component: SecondComponent,
}
]
},
}]})
But if you want to stick up with your structure and check the status of the current route, you can replace beforeRouteUpdate to beforeRouteEnter or beforeRouteLeave in the component. You can use global guard beforeEach in router as well.
To better understand how beforeRouteUpdate works, check out this snippet: http://jsfiddle.net/yraqs4cb/

VueJS how to register global before guards

beforeEach hook for every route like in the docs:
My page should scroll to the top on route change.
const router = new VueRouter({ ... })
router.beforeEach((to, from, next) => {
window.scrollTo(0, 0)
next();
})
but my router has another structure and its not working:
import Vue from 'vue'
import Router from 'vue-router'
import HelloWorld from '#/components/HelloWorld'
import Contact from '#/components/Contact'
Vue.use(Router)
export default new Router({
beforeEach: (to, from, next) => {
window.scrollTo(0, 0)
next();
},
routes: [
{
path: '/',
name: 'HelloWorld',
component: HelloWorld
},
{
path: '/kontakt',
name: 'Contact',
component: Contact
},
]
})
Thanks in advance =)
Or is it better to use the .created hook on the components to scroll to the top of the page?
created() {
window.scrollTo(0, 0);
}
You can adapt your code to the structure required in the docs:
import Vue from 'vue'
import Router from 'vue-router'
import HelloWorld from '#/components/HelloWorld'
import Contact from '#/components/Contact'
Vue.use(Router)
// create object router with the valid initialization
const router = new Router({
routes: [{
path: '/',
name: 'HelloWorld',
component: HelloWorld
}, {
path: '/kontakt',
name: 'Contact',
component: Contact
}, ]
});
// add the beforeEach hook
router.beforeEach((to, from, next) => {
window.scrollTo(0, 0);
next();
});
// export router as default
export default router;
I think you should put Router.beforeEach after creating router.