nuxt-link: pretty URLs with multiple params [no query] - vue-router

let's suppose a very basic structure:
index.vue
_slug.vue
I can create the nuxt-link in this way:
<nuxt-link :to="company.slug">{{ company.name }}</nuxt-link>
And have a pretty URL:
mydomain.com/company-slug
Now in the page component, I can access the param slug thanks to $route.params.slug.
That's ok. But, I would like to pass another param and access it into the page. For example the ID of the company.
How can I achieve that without using the query string?
I would like to keep the URL human-friendly (mydomain.com/company-slug) but pass to the page not only the slug but also the ID (hidden from URL, so no query string).
Thanks

Related

Types of url arguments when linking via <a> tag in django template

What is the difference between these linkings?:
Some Page
and
Some Page .
I've worked with the first one, and can't understand why we need to write like title='title' in the second one.
For the second you are passing 'title' as a string literal to the url parameter title, so this will work if your path looks like:
path('entry/<slug:title>/', some_view, name='entry')
for example. If the path looks like:
path('entry/<slug:slug>/', some_view, name='entry')
the name of the parameter is thus slug, not title. Regardless if you want to pass the value of the title variable, you should use:
Some Page
or in case the URL parameter is slug:
Some Page

Is there a named routes and default params equivalent for Razor Pages page routes?

I have a JobPosts/Index page with multiple GET parameter bindings to allow filtering: let's take CityId and IsRemote for example. I don't want these to be passed as query string parameters, instead I want to use friendly routes for them. So I have defined these:
options.Conventions.AddPageRoute("/JobPosts/Index", "cities/{cityId}/jobs");
options.Conventions.AddPageRoute("/JobPosts/Index", "remote-jobs");
options.Conventions.AddPageRoute("/JobPosts/Index", "jobs");
The routes work just fine when I type them in the browser and the CityId one is bound properly, but two things are missing.
First, there is no way to specify a default value for my IsRemote param, which I want to set to true ONLY when using the remote-jobs URL.
And second, when trying to generate a URL like this:
<a asp-area="" asp-page="/JobPosts/Index" asp-route-cityId="#Model.CityId"></a>
I get the following URL:
https://localhost:44391/jobs?cityId=2265885
When what I actually expect is:
https://localhost:44391/cities/2265885/jobs
So it looks like the tag helper or the part responsible for constructing the URL doesn't look at all at the different routes to try and get a best match based on the list of parameters. Actually, it will always use the last page route defined for that page.
Nor do I have the option anywhere to specify a route name for the page route and then use asp-route to explicitly say which route I want.
Any ideas how to achieve that? Or if it's something that's on the roadmap for Razor Pages?
EDIT: Hardcoding the href is not an option. I want this to go through the proper routing services as there are other things to be done as well, like generating culture-specific URL for non-english users (eg. {cultureId}/cities/{cityId}/jobs - this is done through route conventions. Hardcoding the href would obviously bypass that.
There is a easy way to set IsRemote default value.
public bool IsRemote { get; set; } = true;
This tag asp-page will link to Page /JobPosts/Index.csthml directly,
https://localhost:44391/JobPosts?cityId=2265885
= https://localhost:44391/JobPosts/Index?cityId=2265885
If you are looking forward the URL https://localhost:44391/jobs?cityId=2265885
you could try this a tag to request.
Go to JobPosts
———————————————————————————————
Using a middleware to handle /remote-jobs
app.Run(next => async context =>
{
if (context.Request.Path == "/remote-jobs")
{
return View with default IsRemote
}
});

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

Losing router.params on page refresh

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! 😉

Flask rewrite url

I'm doing a small project that pulls data from tmdb's API.
Right now I have a /tv view that takes an id and request the TV show associated with that id. It results in a url like example.com/tv/23521. Looking at tmdb's own site their URL structure seems to something like "id-slug-title". Regardless of what comes after the ID it still redirects you to the right page.
How is that done? It would seem that it takes in the URL, splits it at "-" and uses the first parameter as ID. I am not sure how to do that in Flask though. I was thinking of using before and after request methods, but I'm worried that will just make unnecessary API calls. In order to get the slug title, I would have to make at least one call with the ID to get the title and then slugify that title.
The route accepts both an id and a slug, where the slug is optional:
#app.route('/tv/<int:id>', defaults={'slug': None})
#app.route('/tv/<int:id>-<slug>')
def tv(id, slug):
# ...
Note that you don't have to do any splitting yourself; the route matches if there is an integer number followed by a dash and some more text, or if it is just a number.
Only the id parameter is needed to find the right page. The slug is simply checked against the 'canonical' and you are redirected if it doesn't match:
page = load_page(id)
if slug != page.slug:
return redirect(url_for('tv', id=id, slug=page.slug))
Don't recalculate the slug each time, just store that in the database. You'll have to load the page info anyway for you to be able to serve it.
You could put that behaviour in a decorator and pass in the loaded page data into the view:
#app.route('/tv/<int:id>', defaults={'slug': None})
#app.route('/tv/<int:id>-<slug>')
#tv_page
def tv(page):
# ...
with tv_page then handling the parameters:
from functools import wraps
def tv_page(view_func):
#wraps(view_func)
def wrapper(id, slug):
page = load_page(id)
if slug != page.slug:
return redirect(url_for('tv', id=id, slug=page.slug))
return view_func(page)
return wrapper