How to get a route param - vue.js

This is how my router looks like:
export default new VueRouter({
mode: 'history',
routes: [
/**
* Authentication
*/
{ name: 'login',
path: '/',
component: Login,
guest: true
},
{ name: 'registration',
path: '/registreer',
component: Registration,
guest: true
},
/**
* Forum
*/
{ name: 'forum',
path: '/forum',
component: Forum,
auth: true
},
]
});
Now I would like to get the auth value when I go to /forum. How do I get that value? I can't find anything in the docs.
Already tried this:
router.beforeEach((to, from, next) => {
console.log(to.auth);
next()
});
But nothing show up, only undefined.
Any ideas?

This is a good use case for Vuex - https://vuex.vuejs.org/en/intro.html
Vuex allows you to maintain the state of the application, and also store various API responses so that you do not have to reload the same data in other components.
In your specific case, your forum component can check the Vuex state if auth is available (this can be done in created or mounted handler). If auth is not available, then you should immediately re-route to auth page using this.$router.replace("/login")
In your auth component or login component, you can do the authentication normally. Once the user login is successful, you can store the server response in this.$store.state["auth"] - the Vuex state that is available globally for all components. This can be done as follows (as a mutation in Vuex store):
Vue.set(state, "auth", currentUserDetailsObject)
Afterwards, you may redirect to forum component, where auth is available in this.$store.state and therefore forum may proceed to display the component normally.
You may need some ramp-up time to get used to the concepts of actions and mutations, but you will find it very helpful for the rest of your app, once you get used to it.

I think you could find what you want here.
And you probably want to know about Vuex.
Then you can write code like this.
if (!store.getters.auth) {
next({
path: '/login',
query: {redirect: to.fullPath}
})
}

Related

How to implement permalinks in a serverless Vue SPA

I made this little app which is a simple Vue serverless SPA. I wish to pass an array of strings and a an array of numbers through the URL so that I can share "states" of the websites with colleagues. I understand vue-routercan update the route's parameters as per their documentation, but I do not have enough perspective to see how to implement this to solve my problem. I would love some help or guidance so I actually learn from this. Thank you all.
EDIT: after Mr. Luis Brito's hint.
I added the following to my code (props)
const router = new Router({
mode: 'history',
base: process.env.BASE_URL,
routes: [
{
path: '/',
name: 'home',
component: require('#/views/Home').default,
props: { myNumbers: [1,2,3]}
},
]
})
in a component I did
mounted () {
this.$router.push({ name: 'myNumbers', params: {myNumbers: [1,2,3,4] }})
const myNumbers = this.$route.params.myNumbers
console.log(myNumbers);
}
But now my App throws a Vue-Router error [vue-router] Route with name 'myNumbers' does not exist but it does console log the numbers I pushed. Is it possible to make my app look for props and only if they are there to do something with them? Otherwise I get a white screen.
The way I see to solve this problem is use vue-router with a route that passes props to the component, that prop can be an object containing the two arrays that you mentioned.
Referer to Vue Router - Obect Mode
Here is an example for the router:
const routes = {
path: '/promotion/from-newsletter',
component: Promotion,
props: { myNumbers: [1,2,3,5,8], myStrings: ['first', 'second', 'third']
}
}
On the component side, you can access those props on created() lifecycle hook, or mounted()
props: ['myNumbers','myStrings '],
mounted() {
if ( this.myNumbers !== undefined && this.myStrings !== undefined ) {
console.log(thys.myNumbers, this.myStrings);
}
}
So that http://localhost:8080/?myStrings=layer1,layer2,layer3&myNumbers=-1,2,3-4 would console log layer 1-3 and the numbers.
EDITED
TO pass the values programatically, would be better to use Function Mode to capture the URL params and pass it to component. Another way would be to create a component where you can input the numbers and strings that you want, and then call the router and pass those values to the route for the final destination component.

How to set and change default(root) router with vue-router(Vue 3 Composition API)

I asked this at two other places but couldn't get a good answer. I would be grateful if anyone here could help me with this. I also think this may help other in the future.
My problem is a bit specific.
I am trying to set the "/" router to for example "/team-12" .
"team-12" is selected by user and stored in localStorage or store(Pinia).
So for example if the user selected a team, the default router will be /team-12/ (".com/team-12/settings" etc.). All the website routing will be added after "team-12/" If not selected it will be team-1 or something like that. And the user can change the team, thus the default route will change and page will refresh.
I managed to set the route to localStorage value but I get an error:
[Vue Router warn]: No match found for location with path "/team-12"
Also I can't add other routes to "/team-12". How can I achieve this? If there is a better aproach, ignore the code.
I tried this: router.ts
router.ts:
const contractId = localStorage.getItem("contractId");
{
path: "/",
name: "home",
redirect: `/${contractId}`,
component: Home,
},
Component:
const selectTeamId = (teamId: string) => {
localStorage.setItem("teamId", organization);
console.log(localStorage.getItem("teamId"));
router.push({ name: "home" });
};

Vue: only allow access to page if redirected to programatically

I have a route which shows after a user has completed a payment, say at the /success URL. How would I make that someone can't simply go to example.com/success and see the success screen. Instead, it should only be accessed by running this.$router.go('/success/'); in code.
Thanks
Take a look at Navigation Guards.
You can add a beforeEnter to the route which you can use to check if the user should access the page.
const router = new VueRouter({
routes: [
{
path: '/foo',
component: Foo,
beforeEnter: (to, from, next) => {
// ...
}
}
]
})
You can do this with router navigation guards, in particular in-component guards. By defining the beforeRouteEnter, you can check (for example) the store, to see if data associated with payments is defined.

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

How to Properly Use Vue Router beforeRouteEnter or Watch to trigger method in Single File Component?

I'm working on an app in Vue.js using Single File Components and Vue Router. I have a Search component where I need to execute a method to re-populate search results each time a user visits the route. The method executes correctly the first time the route is visited because of the "create" hook:
created: function() {
this.initializeSearch();
},
However, when the user leaves the route (to register or log into the app for instance), and returns to the Search page, I can't seem to find a way to automatically trigger this.initializeSearch() on subsequent visits.
Routes are set up in index.js like so:
import Search from './components/Search.vue';
import Login from './components/Login.vue';
import Register from './components/Register.vue';
// Vue Router Setup
Vue.use(VueRouter)
const routes = [
{ path: '/', component: Search },
{ path: '/register', component: Register },
{ path: '/login', component: Login },
{ path: '*', redirect: '/' }
]
export const router = new VueRouter({
routes
})
I gather that I should be using "watch" or "beforeRouteEnter" but I can't seem to get either to work.
I tried using "watch" like so within my Search component:
watch: {
// Call the method again if the route changes
'$route': 'initializeSearch'
}
And I can't seem to find any documentation explaining how to properly use the beforeRouteEnter callback with a single file component (the vue-router documentation isn't very clear).
Any help on this would be much appreciated.
Since you want to re-populate search results each time a user visits the route.
You can use beforeRouteEnter() in your component as below:
beforeRouteEnter (to, from, next) {
next(vm => {
// access to component's instance using `vm` .
// this is done because this navigation guard is called before the component is created.
// clear your previously populated search results.
// re-populate search results
vm.initializeSearch();
})
}
You can read more about navigation guards here
Here is the working fiddle