How to use localeRoute from nuxt-i18n package in vuex - vue.js

I am trying to use localRoute method from nuxt-i18n
this.$router.push(this.localeRoute({ name: "home" }))
I tried this way but it's not working, what is the correct way to do that ?

inside vuex, this.localRoute or this.localPath is undefined because "this" is out of context.
What does work, is passing the whole,localPath object into the action.
So in your method you do this:
test(){
let route = this.localePath({ name: 'forgotPassword' })
this.$store.dispatch('storeTest', route)
},
then inside the action you can do:
storeTest({ commit }, route){
this.app.router.push(route) //this works
$nuxt._router.push(route) //this works as well
},
In the same way, you could pass the whole router into the action if the other options do not work. Then you can do: router.push(route)

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

Pass an object as param to router.push (vue-router#4.05)

Problem
router.push({name:"Order", params: {obj: {}})
fails to push obj: {}, instead the route receives obj: '[object Object]'
Situation
I have a route setup like this
{
path: '/Order',
name: 'Order',
component: () => import("../views/Order.vue"),
props: route => {
return route.params.obj // '[object Object]'
},
}
this results in props not being defined in Order.vue
Expected Result
{
...
props: route => {
return route.params.obj // '{}'
},
}
Based on this answer objects work in older versions
What I've tested
I've used jest to inspect the arguments passed to router.push and they appear as they should: {name:"Order", params: {obj: {}}
Any Ideas?
Passing objects to params was never supported in Vue-router
It sort of worked in Router v3 with $router.push - the target component received the object. BUT as soon as user started using browser navigation (Back button) OR copy/pasting URL's, this solution was broken (you can try it here - just click the button and then use back and forward controls of the frame)
As a rule of thumb - if you want to pass anything to the target route/component, such data must be defined as parameters in the route definition so it can be included directly in the URL. Alternatives are passing data in a store, query params (objects needs to be serialized with JSON.stringify), or using the history state.
This was true for Vue-router v3 and is still for Vue-router v4
Note
Just to explain alternatives. By "store" I do not mean just Vuex. I understand Vuex can be overkill for some small applications. I personally prefer Pinia over existing Vuex. And you can create global state solution yourself with composition API very easily...

How can I send and get with this.$router.push the params between two components

I have two components.
The first one:
This component has this one:
this.$router.push({path: '/dte', params: { id: 1 }});
I am sending and redirecting to /dte
And I have a second one which it has in the created part of the vuejs code this:
export default {
created() {
alert(this.$router.params.id);
}
}
I wonder:
How can I check if id is defined?
I wonder why does it display this error - Error in created hook: "TypeError: Cannot read property 'id' of undefined"?
Thanks
Be careful, there are two globals objects injected by vue-router:
$router: The vue-router instance
$route: The current route state described in an object
Here, you have to check for this.$route.params.id to get the current route parameter.

Nuxt pass props programmatically, through router

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.

Jest spyOn is reporting a method was called with a different object than what it was actually called with

I'm using Jest spyOn to track a method on Vue router. The Vue method I'm testing looks like this:
myMethod() {
this.$router.push({ name: "login" });
}
I want to ensure that $router.push was called, so in my test I have this:
const spy = jest.spyOn(wrapper.vm.$router, 'push');
expect(spy).toHaveBeenCalledWith({ name: "login" });
This test fails, though, with the error:
Expected mock function to have been called with:
{"name": "login"}
as argument 1, but it was called with
{"name": "login", "params": {}, "path": "/login"}.
No problem, I can update the test to the following and it works:
expect(spy).toHaveBeenCalledWith({
name: "login",
params: {},
path: "/login"
});
My question is: why does the Jest spy report that it was called with an object with three properties, but when we look at the actual method call, it only has one property?
vue-router add some default values to params and path properties. When you use spyOn you will detect the other parameters also which are assigned by vue-router. If you add explicit the spy to the push method then you will see only the name property.
Try this:
const spy = jest.fn();
wrapper.vm.$router.push = spy;
expect(spy).toHaveBeenCalledWith({ name: "login" });