I can see previous route in vueDevTools.
How can i access these data from this.$router OR this.$route ??
Updated answer
From your detailed use-case, it looks like you're looking for the initial location your SPA is being loaded on.
For that, you could look into this.$router.history._startLocation and make some conditional based on this.
You can access it from the Nuxt context (available in asyncData, plugins, middleware and nuxtServerInit) like this
<script>
export default {
asyncData({ from }) {
console.log('coming from?', from)
},
}
</script>
Otherwise, you can also access it with Vue-router's navigation guards: https://router.vuejs.org/guide/advanced/navigation-guards.html#navigation-guards
Which can be written this
<script>
export default {
beforeRouteEnter(_to, from, next) {
next((vm) => {
console.log('router guard', from)
next()
})
},
}
</script>
The easiest way would be to get the referer from the header
export async function getServerSideProps(context) {
console.log(context.req.headers.referer)
}
Related
I'm trying to redirect to dashboard after login.
I found this in app.js file that
// make router instance available in store store.$router = router
So I codede that in my login method of auth.js file like below.
store.$router.push({ name: 'dashboard' })
But there is nothing to happen.
How can I use router in vuex store file?
Router is not available in the store directly. You might have to use plugin which makes the router available to the store.
Here is the Vuex-Router plugin which helps to access router to the store.
Are you trying to call router.push in an vuex action?
If so i am doing the same in my quasar v2 project
store/auth/actions.js
import { api } from 'boot/axios'
export function login({ dispatch, commit }, data) {
return api.post('/user/login', data).then(res => {
commit('setToken', res.data.token)
this.$router.push({ name: 'dashboard' }) // <-- What you are looking for?
}).catch(err => {
let msg = err.response.data || 'Error occurred'
return Promise.reject(msg)
})
}
I'm building an editor app which supports multiple design templates. Each design template has wildly different set of fields so they each has their own .vue file.
I'm trying to dynamically load the corresponding view component file based on params. So visiting /editor/yellow-on-black would load views/designs/yellow-on-black.vue etc.
I've been trying to do it like this
{
path: '/editor/:design',
component: () => {
return import(`../views/designs/${route.params.design}`)
}
}
But of course route is not defined. Any idea on how to work around this?
The route's component option is only evaluated once, so that won't work. Here's a solution using a Dynamic.vue view which uses a dynamic component based on the route param.
Use a simple route definition with route param. I changed the param name to dynamic:
import Dynamic from '#/views/Dynamic.vue';
{
path: "/editor/:dynamic",
component: Dynamic
}
Create a generic Dynamic.vue component that dynamically loads a component from the route param. It expects the param to be called dynamic:
<template>
<component v-if="c" :is="c" :key="c.__file"></component>
</template>
<script>
export default {
data: () => ({
c: null
}),
methods: {
updateComponent(param) {
// The dynamic import
import(`#/components/${param}.vue`).then(module => {
this.c = module.default;
})
}
},
beforeRouteEnter(to, from, next) {
// When first entering the route
next(vm => vm.updateComponent(to.params.dynamic));
},
beforeRouteUpdate(to, from, next) {
// When changing from one dynamic route to another
this.updateComponent(to.params.dynamic);
next();
}
}
</script>
i am trying to setup a redirect when the user is not logged in. But when i do it like in my example the URL changes but i get This page could not be found from nuxt. The code is inside an login.js inside the plugins folder. Then i included this in the nuxt config like this.
plugins: [
'~/plugins/login.js'
],
And here is the actual code for handling redirecting
export default ({ app, store }) => {
app.router.beforeEach((to, from, next) => {
const loggedIn = store.state.account.loggedInAccount
if (!loggedIn) {
if (to.path !== '/redirect') {
next({ path: '/redirect' })
} else {
next()
}
} else {
next()
}
})
}
It looks like the routes are not mounted yet.
You should try to use middleware. It is the conventional way to implement the beforeEach function as mentioned by the official docs. You can read about it from here. If have access to the route object, store object and redirect function inside the middleware, so use redirect to direct to the other routes after validation.
I'm new to VueJS and I haven't found a possibility to load components based on route. For example:
page/:pageid
page/one
page/two
I have a component Page.vue
Within that component, I watch route changes. If the route is $pageid, then import and load component $pageid.
I've read this documentation: https://v2.vuejs.org/v2/guide/components-dynamic-async.html. But that's more focussed on lazy-loading. I don't see an example for dynamic importing and loading.
Regards, Peter
According to Dynamic Route Matching of vue router, you can access the url parameters via the params property of the $route object. In your case it would be $route.params.pageid so you can use it to dynamically change the content base on the pageid parameter in the url. Also note that on url change from say in your case page/one to page/two the same component would be used, so you would have to watch the $route object change and change your content dynamically.
watch: {
'$route' (to, from) {
// react to route changes...
}
}
Vue allows you to define your component as a factory function that
asynchronously resolves your component definition.
Since import() returns a promise, so you can register your async component by using:
export default {
components: {
'Alfa': () => import('#/components/Alfa'),
'Bravo': () => import('#/components/Bravo'),
'Charlie': () => import('#/components/Charlie')
}
}
Vue will only trigger the factory function when the component needs to
be rendered and will cache the result for future re-renders.
So your component will be load only when it need to be render.
And you can use dynamic component to render it by using:
<component :is='page'/>
and
export default {
computed: {
page () {
return 'Alfa'
}
}
}
If you already using vue-router you can directly use this in routes definition. See more in document here.
const router = new VueRouter({
routes: [{
path: '/alfa',
component: () => import('#/components/Alfa')
}, {
path: '/bravo',
component: () => import('#/components/Bravo')
}, {
path: '/charlie',
component: () => import('#/components/Charlie')
}]
})
As you can see this is dynamic importing but static registration (you have to provide the path to component.) which fit mostly in many situations. But if you want to use dynamic registration, you can return component directly instead of name see document here.
export default {
computed: {
page () {
return () => import('#/components/Alfa')
}
}
}
In VueJS im trying to setup a scenario where the component used is determined by the url path without having to statically map it.
e.g.
router.beforeEach(({ to, next }) => {
FetchService.fetch(api_base+to.path)
.then((response) => {
router.app.$root.page = response
// I'd like to specify a path and component on the fly
// instead of having to map it
router.go({path: to.path, component: response.pageComponent})
})
.catch((err) => {
router.go({name: '404'})
})
})
Basically, I'd like to be able to create a route on the fly instead of statically specifying the path and component in the router.map
Hope that make sense. Any help would be appreciated.
I think that what you're trying to archive is programmatically load some component based on the current route.
I'm not sure if this is the recommended solution, but is what comes to my mind.
Create a DynamicLoader component whit a component as template
<template>
<component :is="CurrentComponent" />
</template>
Create a watch on $route to load new component in each route change
<script>
export default {
data() {
return {
CurrentComponent: undefined
}
},
watch: {
'$route' (to, from) {
let componentName = to.params.ComponentName;
this.CurrentComponent = require(`components/${componentName}`);
}
},
beforeMount() {
let componentName = this.$route.params.ComponentName;
this.CurrentComponent = require(`components/${componentName}`);
}
}
</script>
Register just this route on your router
{ path: '/:ComponentName', component: DynamicLoader }
In this example I'm assuming that all my componennt will be in components/ folder, in your example seems like you're calling an external service to get the real component location, that should work as well.
Let me know if this help you
As par the documentation of router.go, you either need path you want to redirect to or name of the route you want to redirect to. You don't the component.
Argument of router.go is either path in the form of:
{ path: '...' }
or name of route:
{
name: '...',
// params and query are optional
params: { ... },
query: { ... }
}
so you dont need to return component from your API, you can just return path or name of route, and use it to redirect to relevant page.
You can find more details here to create named routes using vue-router.