Vue Router this.$route.router undefined - vue.js

I'm trying to redirect the url using router.push({ path: 'customers', query : mergedQuery }); but I can't get a correct reference to router property.
I feel like I'm missing something in the app.js but not sure which one. Inside component this.$route has some stuff inside it but there's no router property.
app.js
window.Vue = require('vue');
window.VueRouter = require('vue-router');
window.VueResource = require('vue-resource');
window.Vue.use(window.VueRouter);
const routes = [
{ path: '/', component: require('./components/dashboard.vue') },
{ path: '/customers/', component: require('./components/customers/list.vue') },
];
const router = new VueRouter({routes});
const app = new Vue({router}).$mount('#app');
.vue file
console.log(this.$route.router); //undefined

You're accessing it incorrectly. According to the official docs, router is available inside component instances as this.$router.

Related

Process 404 page when there is no parameter in Vue

Dynamic routing is in use.
If there is no device data in vuex, I want to go to 404 page.
How should I implement it?
router/index.js
const routes = [
{
path: '/',
name: 'Main',
component: Main
},
{
path: '/:device',
name: 'Detail',
component: Detail,
},
{
path: '/:pathMatch(.*)*',
name: 'NotFound',
component: NotFound
},
]
When the device-detail page is implemented as follows, it does not move to the 404 page.
const deviceName = route.params.device
const storedDeviceList = computed(() => store.state.stationName)
if (!storedDeviceList.value.includes(deviceName)) {
router.push({
name: 'NotFound'
})
}
I think the first problem is, that you declare router two times in your project, according to your github repo. You declared your routes in your router/index.js and imported it into your main.js. So importing it again in About.vue from vue-router instead of router.js causes, that this instance has no routes. The second problem is the same with your store, as you import store/index.js to your main.js but import a new instance from vuex to your About.vue.
If you would use the composition API, you could call the already in main.js imported modules with this, like:
this.$router.push({
name: 'NotFound'
})
You also would get your states from your store like this:
this.$store.state.stationName
So, in composition API, use something like this in your About.vue:
<script>
export default {
methods: {
checkDevice() {
if (!this.$store.state.deviceList.includes(this.$route.params.device)) {
this.$router.push({
name: 'NotFound'
})
}
}
},
created() {
this.checkDevice()
}
}
</script>

router is undefined in vuejs

I create done vue js app. In which i have main index.js file for routes and i made different route file for other view and all my child file extend in main index.js route file.
index.js (Main route file)
Below I import my child routes in this file
import test1 from './test1'
import test from './test'
My child route file test1
export default [{
path: '/roles',
component: Layout2,
children: [{
path: '/',
component: () => import('#/views/test/test1'),
meta: {
auth: true
},
beforeEnter(to, from, next) {
if(checkPermission("readUser")){
router.push({
name: 'unauthorized'
})
}
}
}
}]
}]
Now issue is i am trying push unauthorized in url by using before route, but it gives me error like router is not defined. How can i solve this issue?
I think you should creater router instance first, and export it.
export const router = new VueRouter(routes)
const routes = {
path: '/roles',
component: Layout2,
... etc.
}
Then import router into main js file.

Why isn't router.currentRoute.path reactive?

I have an app which is contained in this div:
<div id="app" v-bind:style='{backgroundColor: backgroundColor}'>
... the app ...
</div>
The routing is done following the example in the documentation (this is a webpack project):
import Vue from 'vue/dist/vue.js'
import VueRouter from 'vue-router'
import ComponentOne from './component1.vue'
import ComponentTwo from './component2.vue'
Vue.use(VueRouter)
const routes = [{
path: '/foo',
component: ComponentOne
},
{
path: '/bar',
component: ComponentTwo
}
]
const router = new VueRouter({
routes // short for `routes: routes`
})
const app = new Vue({
router,
data: {
day: "Monday"
},
computed: {
backgroundColor: function () {
console.log(JSON.stringify(router.currentRoute))
if (router.currentRoute.path == "/foo") {
return "green"
} else {
return "blue"
}
}
}
}).$mount('#app')
I wanted the background to be dependent on the current route (router.currentRoute.path).
But, the solution above does not work, because router.currentRoute.path is not detected by the Vue instance as having changed (is not reactive).
What is the correct way to access the dynamic router data from within the Vue instance?
The router object created via new VueRouter is not reactive because Vue has no way to know to watch and update any object outside of its scope.
Passing router in the Vue config object is what allows the current route to be watched, but you need to reference it via this.$route:
if (this.$route.path == "/foo") {
...
}
You can also access the entire router object via this.$router, but its data is not reactive.
And if you are using Vue 2 with composition api setup() approach you can do this:
import { computed } from '#vue/composition-api'
export default {
setup (props, context) {
const params = computed ( () => context.root.$route.params)
const path = computed( () => context.root.$route.path)
I found on Vue's documentation page that tracks the router using watch for transition animations. Not sure if this is a best practice but you can use to.path or from.path to grab the path instead.
// then, in the parent component,
// watch the `$route` to determine the transition to use
watch: {
'$route': (to, from) => {
const toDepth = to.path.split('/').length
const fromDepth = from.path.split('/').length
this.transitionName = toDepth < fromDepth ? 'slide-right' : 'slide-left'
}
}

vue-router 2, how to fetch routes via ajax?

How do I create the routes array dynamically, after fetching it via ajax?
Is there a way to add/push new routes to the router after it has been initialized?
This doesn't work:
new Vue({
el: '#app',
template: '<App/>',
data: {
content: []
},
created: function () {
this.$http.get('dummyjsondatafornow').then((response) => {
// this doesn't work when creating the VueRouter() outside the Vue instance, as in the docs.
// this.$router.options.routes.push({ path: '/about', component: About })
let routes = [
{ path: '/about', component: About }
]
// this doesn't work either
this.router = new VueRouter({
routes: routes
})
})
},
// router: router,
components: { App }
})
I don't believe there is no.
That said you can wildcard the route so that may provide you with an alternative.
I built a site where the backend (and in turn pages created) were controlled via a CMS which served all pages to Vue as JSON. This meant Vue wasn't aware of the routes the backend was creating.
Instead we passed all the CMS pages to Vue Router via a single * wildcard component. In Vue Router 2 this would look like:
const routes = [
{ path: '*', component: AllPages }
]
Vue Router 2 allows for Advanced Matching Patterns
These allow you to set a wide variety of conditions, therefore whilst you can't inject the object passed back via ajax into your router you can add a dynamic component to an AllPages component that is wildcard matched. This would allow you to pass the name of the component to load via your ajax request and then load that component when the page is called. i.e.
Your Ajax response:
{
// url: component name
'/about/': 'about',
'/about/contact/': 'contact',
...
}
Then in an AllPages vue component:
<template>
<component v-bind:is="currentView"></component>
</template>
<script>
module.exports = {
data () {
return {
currentView: '',
ajaxRoutes: {}, // loaded via ajax GET request
...
}
},
// watch $route to detect page requests
watch: {
'$route' (to, from) {
if (this.ajaxRoutes[to]) {
this.currentView = this.ajaxRoutes[to]
}
}
},
...
}
</script>
The above is a rather abbreviated idea but essentially you dynamically load the component based on the path the user requested.
I think this is fixed in version 2.3.0. You can now run
router.addRoutes(routes);
to dynamically add routes.
https://github.com/vuejs/vue-router/commit/0e0fac91ab9809254174d95c14592e8dc2e84d33
I have the same situation wherein my routes are built on the backend as it is maintained thru a CMS. With that, I was able to retrieve my routes thru an API call then return it on the vue router. Here's my take:
routes.js
const router = store.dispatch('cms/fetchRoutes').then((response) => {
const router = new VueRouter({
routes: response,
mode: 'history',
...
});
...
return router;
});
export default router;
main.js
import router from './router';
....
router.then((router) => {
const app = new Vue({
router,
store,
render: (h) => h(App),
}).$mount('#app')
...
});
Basically I do an axios call to fetch my routes then inject the response to the VueRouter routes property. Then on the main.js, do another then and inject the return on the Vue.
By then, my menus are now being retrieved from the database. No more hard coded paths.

Vue router and Bootstrap

I'm using Vue with vue-router and vue-strap. I'm trying to register components from vue-strap, but the examples look like this:
var alert = require('vue-strap').alert;
new Vue({
components: {
alert: alert
}
})
vue-router, on the other hand, doesn't create a Vue object.
Vue.use(VueRouter);
const router = new VueRouter({
history: true,
linkActiveClass : 'active'
});
router.map({
'/': {
component: Home
}
});
const App = Vue.extend(Index);
router.start(App, '#root');
So how do I declare my components?
This is my current setup in vue apps
var Vue = require('vue');
var VueRouter = require('vue-router');
// Use
Vue.use(require('vue-resource'));
Vue.use(VueRouter);
// Components
var site = Vue.component('site', require('./views/site/component.vue'));
var home = Vue.component('home', require('./views/home/component.vue'));
var search = Vue.component('search', require('./views/search/component.vue'));
var index = Vue.component('index', require('./views/index/component.vue'));
// Router
var router = new VueRouter({
history: true
});
router.map({
'/': {
component: index
},
'/search': {
component: search
},
'/profile': {
component: home
}
})
// Start App
router.start(site, 'body');
All 'major' components are declared globally with .component. Everything that I need at component level I declare with .extend. In vue-router, the 'site' component (in my case) acts as the $root.
Topmenu / sidebar are declared in the site component in the components section.
In the 'site' template i have only and other shared components like topmenu / sidebar.
you can try it instead,
import { alert } from 'vue-strap'
Vue.use(VueRouter);
const router = new VueRouter({
history: true,
linkActiveClass : 'active'
});
router.map({
'/': {
component: alert
}
});
const App = Vue.extend(Index);
router.start(App, '#root');