How to get http refere in vuejs? - vue.js

I would like to get from which page a user came from in my page.
Currently, I would like to get this info in my created() or mounted() pages. Using this.$router or this.$route but none of them contain this info.
I know in the navigation guards, we can use this :
router.beforeEach((to, from, next) => { })
to know where the page is comming from, but I don't want to use router.beforeEach because that is in found inside my main.js but where I want to get the referer is in my components page, either in created/mounted methods
Is this possible?

You can use this.$route.query in mounted() hook in App.vue. You don't need router.beforeEach, because it dosn't make sense. App.vue mounted one time, when app is loaded, so this a good place to check router query params.

router.beforeEach((to, from, next) => {
console.log(to.query)
console.log(to.query.utm_source)
})
if url product/3?utm_source=2.
Console logs
{utm_source: "2"}
2

Related

How to render a page content with dynamic routing on page reload?

I have a SPA with dynamic routing. On page loading I'm making a fetch request for products. Then set it to the vuex store and use it. I also have a dynamic routing for product pages '/product/:id'
The problem is if I reload a product page say site.com/product/2 then nothing renders. I think this happens because at that moment store is empty and there're nothing to render.
How can I fix that?
In ProductPage component I tried using navigation guard with no success. Code below returns error: Cannot read properties of undefined (reading 'products').
Fetch request is made on mounting in TheMain component (when I reload ProductPage fetch request is made as well).
ProductPage component:
computed: {
...mapState(["products"]), // get products array from store
},
beforeRouteEnter(to, from, next) {
if (this.products) { // check if products array exists and then load data
next(true);
}
},
I think you need to make beforeRouteEnter async and add await for the store action which does the fetch or axios call.
async beforeRouteEnter(to, from, next) {
if (this.products) {
// check if products array exists and then load data
await dispatch(‘action_to_get_data’);
/// Wait to go to next for dispatch to finish.
next(true);
}
}
In your action you also need to use async / await.
What also might help is a v-if on the ProductPage component, so the components only loads when the products are loaded in the store.
For vue3 you may also take a look at the experimental Suspense component. But I don’t know if this works with beforeRouteEnter.
Hope this helps.

How can I set a default value on router.back() for deep linked items in VueJS

I have two (or more) VueJS routes that contain a router-link pointing to the same third route.
/pages/list
<router-link :to="{name:'add-page'}">Add</router-link>
/pages/other-list
<router-link :to="{name:'add-page'}">Add</router-link>
If I put a put link on the third page with $router.back(), the link will take me back in history to whichever previous page I came from.
However, if enter the add-page route directly into my browser, there is no history. I would like to set a default value for that page, and preferably not rely on a global default.
What is the best way to select a default route if there is no history on a specific component?
Would a Navigation Guard fits your needs?
You would use it something like:
router.beforeEach((to, from, next) => {
if (to.name === 'add-page' && to.) {
//Your logic here
//eg a redirect
next({ name: 'MyBaseRoute' })
} else {
next()
}
})
or if you need just for a selected component you can use the in-component guard:
beforeRouteEnter (to, from, next) {
// called before the route that renders this component is confirmed.
// does NOT have access to `this` component instance,
// because it has not been created yet when this guard is called!
},

Load values into vue.js router guard before it is called

I am setting up a vue.js router guard in my main.js file.
But i have a list of entitlements that needs to be passed into that router guard.
I am fetching the needed entitlement list into the store in my App.vue created method - but i think it is too late for the router guard.
My entitlement list is not available to the guard at the time it is initialized.
Where can i load the entitlements so they will be ready for the guard when it needs them?
router.beforeEach((to, from, next) => {
entitledBeforeEach(to, from, next, store.getters.ENTITLEMENTS); });
that getter will always return null because main.js has not fetched the entitlements yet.
How can i do that sooner?
In your store, use an action instead of a getter. The actions can be async, and should resolve once your entitlements are loaded or reused from a previous request.
router.beforeEach((to, from, next) => {
store.dispatch('getEntitlements').then(entitlements => {
// Do your processing and setup here.
// There are many ways to get the entitlements into your component...
next();
});

Nuxt - How to find the previous route?

I am able to use this.$router.go(-1) to redirect a user to the previous route. However, I am not able to understand how I get get the information about the previous route before redirecting.
Basically, by first reading what the previous route was, I want to make sure that the previous route was from the same domain and only then redirect to it, otherwise do something else.
in nuxt static methods where you have access to nuxt context ex: asyncData or middlewares :
asyncData({from}){
// do something with from
}
but if you want to get the prev route in vue instance you can use
this.$nuxt.context.from
also, remember that from can be undefined if there wasn't any prev page in the browser history
In your page you can add asyncData hook which have access to context object with from property:
asyncData({ from }) {
console.log(from);
}
You can achieve this by implementing the Vue Navigation guards, on the component/page.
<script>
export default {
beforeRouteEnter(to, from, next) {
console.log(from)
next()
},
data() {
return {
...
prevRoute: null,
}
}
}
</script>
Or there is this guy https://gist.github.com/zolotyx/b4e7fda234b3572fb7adaf11391f8eef#file-auth-js, he has made a script to help in redirecting
There is no out of the box way to get this information.
What you can do is attach a beforeRouteEnter as a global guard and save the route before navigating to a new route.
Then you can check to see if there is a previous route saved and execute this.$router.go(-1)
If you are using the router in history mode you could be tempted to use the History api that vue-router is using to get this information. But HistoryApi doesn't allow for this as this would be a huge privacy problem. You could see the entire history of the user in the current tab.
In the [middleware] directory you can put this script [routing.js]:
/* eslint-disable no-undef */
/* eslint-disable no-console */
export default function (context) {
// current route
console.log('route=', context.route.name)
// previous route
if (process.client) {
const from = context.from
console.log('from=', from)
}
}
In [nuxt.config.js]:
router: {
...
middleware: 'routing'
},
Whenever you change the current page in the client you should see a log showing the previous page. Maybe it can help you.

Vue.js with VueRouter - how to correctly route on user's refresh

I use Vue and VueRouter (and also Vuex but it is not the case here) in my project. Imagine i have 5 files:
main.js - stores all components definitions, imports them from
external files and so on.
App.vue - it is main component that stores
all other
routes.js - stores all the routing definitions
login.vue -
stores login component (login page)
content.vue - stores page
component
(quite simplified version but you surely get the idea).
Now if i open my path '/' it should reroute me to '/login' page if i am not logged in and to '/content' when i am logged in. Nothing special here.
Now my page works as intended (almost). If I enter in my browser '/content' it tries to render '/content' component with default data (ie userId = -1), then immediately it reroutes me to '/login' page. The '/content' shows just for a second. And it is my problem. I would like to reroute to '/login' without earlier rendering '/content' with default data.
It is obvious that it tries to render '/content' - maybe from cache or something, but since rerouting is my first command in created() it should not
mount /content component in app component, but /login.
Any idea how to prevent it?
I am aware that i do not attach any code, but i hope it wont be necessery for you to understand the problem and advice any solution because it would need cutting and simpliding a lot of code.
In your case, I think you should use vue router's beforeEach hook.
You can use meta field in router to indicates whether the path need authentication, and do processing in beforeEach function.
I will give the sample code.
import Router from 'vue-router';
const router = new Router({
routes: [{
path: '/content',
meta: {
auth: true,
}
}, {
path: '/login',
}]
});
router.beforeEach(async (to, from, next) => {
if (to.matched.some(m => m.meta.auth)) {
// user your authentication function
const isAuth = await getAuthentication;
if (!isAuth) {
next('/login');
}
next();
}
})
if your authentication function is not async function, you should remove async/await keywords
Except if the API in the meantime declares that you are no longer authenticated, the router will not be able to refresh itself by the beforeEach method.
Even with a loop method that retrieves data from the API, which will store them in the store as reactive data.
In Vue everything can be reactive, except Vue router