Nuxt pass props programmatically, through router - vue.js

i'm using Nuxt
I'm having troubles with passing data from one page to another
I would like programmatically to navigate to other page, and pass some data to other page (in this case its javascript object)
So here is my code so far:
I have a component in which I navigate from:
this.$router.push({ path: 'page/add', props: { basket: 'pie' } });
And here is a component where I would like to get data, its a Nuxt page:
export default {
components: { MyComponent },
props: [
'basket' // this is also empty
],
async asyncData(data) {
console.log(data); // data does not contain basket prop
},
meta: {
breadcrumb: {
path: '/page/add',
},
},
};
</script>
But when I try to acces props, or data or data.router it does not contain basket prop ??
Also, I would not like to use query, or params because they change URL
[1]: https://nuxtjs.org/

You can use localstorage and save you'r data in it:
localStorage.setItem("nameOfItem", Value);
and delete it if you want after you'r done with it:
localStorage.removeItem("nameOfItem");

If you don't want to use query or params, I would check out the vuex store. Its a really cool way of storing global variables and use it in multiple pages.
Vuex store

Navigate to a different location
To navigate to a different URL, use router.push. This method pushes a new entry into the history stack, so when the user clicks the browser back button they will be taken to the previous URL.
The argument can be a string path, or a location descriptor object. Examples:
// literal string path
this.$router.push('/users/eduardo')
// object with path
this.$router.push({ path: '/users/eduardo' })
// named route with params to let the router build the url
this.$router.push({ name: 'user', params: { username: 'eduardo' } })
// with query, resulting in /register?plan=private
this.$router.push({ path: '/register', query: { plan: 'private' } })
// with hash, resulting in /about#team
this.$router.push({ path: '/about', hash: '#team' })
reference:
https://router.vuejs.org/guide/essentials/navigation.html#navigate-to-a-different-location

To navigate to a different URL, use router.push. This method pushes a new entry into the history stack, so when the user clicks the browser back button they will be taken to the previous URL.
What you are trying to accomplish is not conform with the browser (history etc.) or
http protocol (GET/POST).
Also, when using path params and other variables, such will be ignored, as per the documentation.
Note: params are ignored if a path is provided, which is not the case for query, as shown in the example above. Instead, you need to provide the name of the route or manually specify the whole path with any parameter.
Using props here is very likely the wrong approach, as you will never get that data to the component.

Related

Vue3: How to send params to a route without adding them to the url in Vue3?

In Vue3 is there a way to pass properties to a route without the values showing in the url?
I defined the route like this:
{
path: '/someRoute',
name: 'someRoute',
component: () => import('#/app/pages/SomeRoute.vue'),
props: (route) => {
...route.params
}, // <-- I've seen this method in Vue2 but in Vue3 the route.params is just empty here
}
I call the route like this:
<router-link :to="{ name: 'someRoute', params: { message: 'Some Message' } }">Some link</router-link>
When I change path into path: '/someRoute/:message', the message come through just fine but I just want to pass the message without it showing up in the url.
I've seen a couple of Vue2 examples that use this method (e.g. https://stackoverflow.com/a/50507329/1572330) but apparently they don't work in Vue3 anymore.
Also all the examples in the Vue3 docs (https://github.com/vuejs/vue-router/blob/dev/examples/route-props/app.js / https://v3.router.vuejs.org/guide/essentials/passing-props.html) pass on their values through the url itself so I'm not sure if it's even possible anymore.
Any thoughts on this would be helpfull.
Finally I found something about this in the changelog: https://github.com/vuejs/router/blob/main/packages/router/CHANGELOG.md#414-2022-08-22
Apparently it's no longer possible to send properties via params without the showing in the url. But fortunately they give some alternative suggestions.
The one that worked best for my situation was to use state: { ... } instead:
<router-link :to="{ name: 'someRoute', force: true, state: { message: 'Some Message' } }">Some link</router-link>
Now in the code of the page I read the property from the history.sate and put the value in whatever property I need it.
In case the url/route itself doesn't change you need to have an update hook and use force: true
public created() {
this.message = window.history.state.message;
}
public updated() {
this.message = window.history.state.message;
}
PS history.state has some limitations so in other situations one of the other suggestions from the changelog might work better

how can I change only a param like an id in my URL

I have a have a list of links inside a childcomponent which is integrated in different pages and if I click on a link, I need to get an id back, but I need to keep the current URL with the new id to call another method.
this.$router.push({path: '/page/', params: {id:id}})
this.$router.push({path: '/otherpage/', params: {id:id}})
I tried several things which are not working, like
this.$router.push({path: this.$router.currentRoute, params: {id:id}})
to get the following on different pages
http://domain/page/1
or
http://domain/otherpage/1
if I hardcode the path it works with:
this.$router.push(`/page/${id}`)
but I like to reuse the component on any page
thanks to Igor I ended up with the following:
const path = `/${this.path}/${node.id}`
if (this.$route.path !== path) this.$router.push(path)
thanks
From vue-router docs:
Note: params are ignored if a path is provided...
https://router.vuejs.org/guide/essentials/navigation.html
Instead of providing the path, you should call this.$router.push() with the route name, and the desired params.
For your example:
this.$router.push({name: this.$router.currentRoute.name, params: {id:id}})
This approach assumes that your routes are named, like this:
const routes = [
{
path: "/page/:id",
component: () => import('/path/to/component.vue'),
name: "nameOfTheRoute",
// other attributes
},
//...
]

Accessing $route from Vue.js in SPA

Im trying to accesing meta data from my route in vue.
In routes.js I have for example:
{ path: '/product/:productSlug',
name: 'product.slug',
meta: { layout: "no-snackbar" },
hide: true,
component: require('~/pages/checkout/product'), },
It is no-snackbar I need to access.
Then in App.vue I'm checking to see if this is set:
mounted () {
console.log(this.$root.$route.meta.layout)
}
This console.log outputs undefined. If I console.log this.$root.$route I get the following (the same for this.$route):
fullPath: "/"
hash: ""
matched: []
meta: {empty}
name: null
params: {empty}
path: "/"
query: {}
This is not the right path, name, or ofcause meta data. All is empty. Then when I check in Vue devtools, all settings are correct - also the meta data in $route.
This indicates that the values have yet not been set at the point of logging, since they are "visible" later. If I console.log(this.$root.$route.meta.layout) in a page (not App.vue) in mounted(), all values are also present as they should.
The problem is therefore in App.vue.
What am I missing in order to be able to access $route values in App.vue?
You can use currentRoute via this.$router from any component.
I'm not sure if using mounted() to do this in App.vue will work, but updated() will.
updated() {
console.log(this.$router.currentRoute.meta.layout);
}
Try visiting the route in your browser first for example localhost:3000/product/foo then in your mounted method in App.vue add:
mounted () {
console.log(this.$router.currentRoute.meta.layout)
}
NOTE: You need to be in the route that has the meta property defined in your routes.js or else you will keep getting the undefined error.
To avoid getting the undefined error add the meta property to every route in your routes.js.

Data passing using props in router is not working

I am trying to send data from one vue component to another by using props in router. but it is not working. whenever i try to log the props it outputs undefined. code is given below
From where data is sending
Where receiving
in index.js. router setting
None of the code you've posted matches up.
Firstly, the console logging should be just console.log(this.myprops). The point of using props is that you don't need to reference the router itself, e.g. via $router.
Next problem, you're mixing path and params. That isn't allows. See https://router.vuejs.org/guide/essentials/navigation.html. params are for named routes.
I imagine what you're aiming for is something like this:
self.$router.replace({ name: 'DashboardPatient', params: { myprops: authUser.email } })
with router config:
{
path: '/patient',
component: Dash,
children: [
{
path: ':myprops', // <--- Adding myprops to the URL
name: 'DashboardPatient',
component: DashboardPatient,
props: true,
meta: { requiresAuth: true }
}
]
}
Keep in mind that routing is all about building and parsing the URL. So the value of myprops needs to be in the URL somewhere. In my example it comes at the end, so you'll get /patient/user#example.com as the URL. If it weren't in the URL then there'd be no way for the router to populate the prop if the user hit that page directly (or refreshed the page).
To hit the same route using a path instead of a name it'd be something like this:
self.$router.replace({ path: `patient/${encodeURIComponent(authUser.email)}` })
or even just:
self.$router.replace(`patient/${encodeURIComponent(authUser.email)}`)
Personally I'd go with the named route so that the encoding is handled automatically.
If you don't want to put the data in the URL then routing is not the appropriate way to pass it along. You'd need to use an alternative, such as putting it in the Vuex store.

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