Losing router.params on page refresh - vue.js

I'm encountering an issue with vue-router.
I got a list of posts in the homepage. When I click on one of them, it redirects to the post page such as :
<router-link :to="{ name: 'article', params: {id: article.id, slug: article.slug } }"></router-link>
Everything is working perfectly, I can retrieve the data of the correct article using this.$route.params.id in a getter.
My issue : When I reload on an article page, this.$route.params.id is undefined, which causes the entire application to crash.
How can I save the router.params despite a page reload ?

What backend are you using? You need to enable history mode on your router, as well as make some additional configuration changes on your backend web server. Please refer to this link for the additional server side configuration changes you will need to make for this to work properly.
Also, please make note of this 404 caveat when using history mode..
Edit: you could try something like this since the ID remains persistent in the URL: Look for the solution from MIKE AXLE
I don't know if anyone else if facing the same issue, but I was having a problem getting route params on refresh. The route parameter I was trying to get was an ID number and I use that ID to fetch data and populate the page. I found (through many console logs) when I refreshed, the number was turning into a string and thats why the page was not working. I sorted it out but casting the ID to number before using it:
Number($route.params.id)

You can also use query instead of params
<router-link :to="{ name: 'article', query: {id: article.id, slug: article.slug } }"></router-link>
and to get value on redirecting page
this.$route.query

I'm not sure what is your route definition, the problem can be that only one of the params presented in the route URL (e.g. /article/:slug).
When you invoke a route (by clicking on router-link or calling router.push), you passing both params directly and they persist in the memory. That's why both are accessible.
But when you reload the page - everything that Vue can do is to parse your URL.
Means only one param parsed because only one param is present.
As a solution you can:
use both params in the route URL (e.g. /article/:id/:slug);
or use one param and call your API to retrieve remaining information (e.g. get id by slug if your route is /article/:slug).

I had the same issue pass the url in router
/article/:id/:slug
you will not loose your params after resfresh because whenrefreshng vue will take only data from url and forget if you passed params

You should route like this:
{
path: '/article/:id/:slug',
name: 'article',
}
In your view when routing do it like this:
this.$router.push({ name: 'article', params: { id: articleID, slug: articleSlug}});
You're welcome! 😉

Related

vue router.push in nuxt using route.name

I use nuxt and have following Problem. My old code looks like this:
this.$router.push({path: "about/me"})
Now I need to make the same call with some params:
this.$router.push({path: "about/me", params: {sendNotification: "1"}})
This obviously doesn't work since vue-router only allowes to use params with name and not path, so it has to look like:
this.$router.push({name: ..., params: {sendNotification: "1"}})
I could do it with query instead of params but I don't want my url to look ugly.
The problem with nuxt is, or at least this is my understanding of nuxt, that it generates the route names using folder structure and in my case also the locale. So the name of this route is actually: "personal-about-me__en".
So my question: Is there a way to get the route.name dynamically, so I could write something like:
this.$router.push({name: getRouteNameByPath("about/me"), params: {sendNotification: "true"}})
The name of the route path is matching the name prop that you can give to the .vue file. So, write is as name: 'AboutMe' key property and use it in the router with { name: 'about-me' }.
Also, vue devtools have a router tab with the name of all the available routes.
This obviously doesn't work since vue-router only allowes to use params with name and not path.
Why do you need to pass params alongside the path? You are supposed to add the params to the path itself, which is why vue-router doesn't allow a separate params object.
So for e.g. assuming your dynamic route is about/me/:sendNotification, you can either provide params with the named route:
this.$router.push({name: ..., params: {sendNotification: "1"}});
which directs you to about/me/1.
OR you can push the entire path including the params
this.$router.push({ path: 'about/me/1' });
Both will produce the exact same result.

Generate aurelia route with parameters and open in new browser tab

I need to open a page in new tab with defined parameters.
Before I used only one parameters and it works fine:
window.open(this.theRouter.generate('transactionDetails', { id: id }), '_blank');
But now I need to add two more parameters.
I tried the following:
window.open(this.theRouter.generate('transactionDetails', { id: id, localtimezone: this.localTimeZone, reporttimezone: this.reportTimeZone }), '_blank');
But as result I can see in URL this:
http://localhost:54072/index.html#/transactionDetails/28789?localtimezone=3&reporttimezone=0
What I do wrong? How I can generate url with some parameters?
Thanks in advance.
You have to decide how to pass parameters.
The way your example looks it seems your route declares the "id" parameter.
If you declare parameters, the most consistent way is to declare every parameter in an analogous way:
route: "transactionDetails/:id/:localtimezone/:reporttimezone",
this way you get something like this:
#/transactionDetails/123/1608260750758/1608260750758
another way is to use query string and not use router params:
route: "transactionDetails",
this way, you get the url: #/transactionDetails?id=123&localtimezone=1608260810884&reporttimezone=1608260810884
a working example is available at
https://codesandbox.io/s/aurelia-router-demo-forked-wyszo?file=/src/app.js:356-384
Regards.
Cristian

Nuxt encode/decode URI with double colon

My URLs have double colon on them.
I push a path to Nuxt router which has : as a part of it.
export default {
router: {
extendRoutes (routes, resolve) {
routes.push({
name: 'custom',
path: 'towns' + '(:[0-9].*)?/',
component: resolve(__dirname, 'pages/404.vue')
})
}
}
}
When I point to http://localhost:3000/towns:3 , for example, the : is translated as %3Aon the URL leading to this error message:
Expected "1" to match ":[0-9].*", but received "%3A2"
How to revert this to : ?
I tried encodeURI(), decodeURI(), encodeURIComponent() and decodeURIComponent() in vain.
A demo for the ones who wants to try: nuxt-extend-routes
Any suggestions are welcome
Vuex is using vue-router and vue-router is using path-to-regexp to parse router path configuration
It seems to me, that you are trying to use Unnamed Parameters which doesn't make sense because vue-router/vuex need the name of the parameter to pass it down to Vue component behind the route
Why don't just use named parameters ?
{
path: '/towns:id(:\\d+)',
name: 'Page 3',
component: Page3
}
Sure, result will be that $route.params.id value will be prefixed with : and all router-link params must be :XX instead of 'XX' but that's something you can deal with. vue-router (path-to-regexp) is using : to "mark" named path parameters ...there's no way around it
You can take a look at this sandbox. Its not Nuxt but I'm pretty sure it will work in Nuxt same way....
Update
Well it really doesn't work in Nuxt. It seems Nuxt is for some reason applying encodeURIComponent() on matched path segments and throws an error. It works when server-side rendering tho (it throws some error on client still)...
Firstly, I concur with Michal Levý's answer that there's a library bug here. The line throwing the error is here in the Nuxt source:
https://github.com/nuxt/nuxt.js/blob/112d836e6ebbf1bd0fbde3d7c006d4d88577aadf/packages/vue-app/template/utils.js#L523
You'll notice that a few lines up the segment is encoded, leading to : switching to %3A.
However, this line appears to have originated from path-to-regexp:
https://github.com/pillarjs/path-to-regexp/blob/v1.7.0/index.js#L212
It isn't trivial to fix this bug because the encoding is not simply 'wrong'. There's a lot of stuff going on here and by the time that line is reached the parameter values have been URL decoded from their original values. In the case of our unencoded : that causes problems but in other cases, such as matching %3A, the encoding would be required.
The handling of encoding within path-to-regexp is a delicate topic and we aren't helped by the old version being used. This also makes it more difficult to come up with a suitable workaround in your application.
So, let's see what we can do...
To start with, let's consider the path:
path: 'towns' + '(:[0-9].*)?/',
Bit odd to concatenate the strings like that, so I'm going to combine them:
path: 'towns(:[0-9].*)?/',
The / on the end isn't hurting but it seems to be unnecessary noise for the purposes of this question so I'm going to drop it.
On the flip side, not having a / at the start can cause major problems so I'm going to add one in.
The .* is suspicious too. Do you really mean match anything? e.g. The current route will match towns:3abcd. Is that really what you want? My suspicion is that you want to match just digits. e.g. towns:3214. For that I've used [0-9]+.
That leaves us with this:
path: '/towns(:[0-9]+)?',
Now, the : problem.
In general, route paths are used in both directions: to match/parse the URL and to build the URL. Your use of an unnamed parameter makes me wonder whether you only intend to use this route for matching purposes.
One option might be this:
path: '/towns:([0-9]+)',
By moving the : outside the parameter it dodges the encoding problem.
There are two problems with the code above:
The colon/number suffix is no longer optional on the URL. i.e. It won't match the path /towns as the original route did. This can be solved by registering /towns as a separate route. I'm not aware of any other way to solve this problem with the available version of path-to-regexp.
You won't be able to use it to build URLs, e.g. with nuxt-link.
If you need to be able to use it to build URLs too then you could use a named parameter instead:
path: '/towns::town([0-9]+)',
The :: part here is potentially confusing. The first : is treated literally whereas the second : is used as a prefix for the town parameter. You might then use that with nuxt-link like this:
<NuxtLink :to="{ name: 'custom', params: { town: 4 } }">
...
</NuxtLink>

how to set multiple values for query params in vue-router's router-link

Using vue-router's <router-link>, I want to redirect a user to a path like so /projects/7363994/posts?t=apples+oranges&s=all.
Where t means topics, and s means sources (facebook, twitter, forums etc).
ie for project 7363994, look for posts whose topics includes apples and oranges and from all sources.
such that, on page load for /projects/:id/posts endpoint, the component will first check for those params and make queries to an API for data according to those param values.
this is what I have tried:
<router-link
:to='{
path: `posts`,
query: {
t: "apple+orange",
s: `all`
}
}'
append
>
</router-link>
which gives me /projects/7363994/posts?t=apples%2Boranges&s=all.
i was expecting the link to show up as:
/projects/7363994/posts?t=apples+oranges&s=all
but instead, it is showing:
/projects/7363994/posts?t=apples%2Boranges&s=all
notice that the + symbol has been replaced with %2B
why is that so? am I supposed to do some escaping?
also tried this:
<router-link
:to='{
path: `posts`,
query: {
t: ["apple", "orange"],
s: `all`
}
}'
append
>
</router-link>
gives me /projects/7363994/posts?t=apples&t=oranges&s=all
I tried escaping the + symbol, but that doesn't seem to work as well.
anyone knows how this works? does vue-router even allow this to begin with?
thanks!
The url is encoded so on the server side you have to decode the url for its working
When setting the value use
decodeURIComponent(t)
this will make the coded url to decode one

Vue.js getting params from router-link bind

How can I get the params giving not trough the url but trough a post like params?
<router-link v-bind:to="{
path: '/city/'+city.topicID,
params: { countryCode: countryCode, city: city } }">
Chat
</router-link>
this.$route.params does not seem to work and will on show the topicID.
In the router-link documentation, it mentions that router-link just passes the contents of the "to" to router.push().
In the router.push() documentation, it mentions that if you have both a "path" and "params", the params are ignored. Specifically, it says:
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
So, you'll need to use a named route if you wish to use params, and then build your path in the named route definition.