Now in this core section,
I'll continue working on this
Share a Restaurant site here,
which we worked on in the previous section.
And attached you'll find a snapshot of this project
so that we can all start on the same page.
And I wanna start by adding a new feature,
a new page to this project.
At the moment, we can view a list of all restaurants here,
and we can then view the website of a restaurant,
but I actually want to tweak this a little bit.
And for that, I wanna replace this button here,
this view website button with a button that takes us
to a detail page of this restaurant.
And then on that detail page
we can go to the website, but most importantly,
we'll then have one page per restaurant,
which we could also share with other people
because at the moment,
it's quite hard to share one specific restaurant
with a friend,
because you can only share this list of restaurants.
And then you have to tell your friend,
"Hey, I'm talking about the second one."
So having a detailed page that you could share
would be way more useful
and that's what we wanna implement now.
And therefore we'll have to add such a detail page,
we'll have to change this button
and we'll have to add some Express code
to serve that detail page.
Now to achieve this goal,
I'll start by going to my views
and then to this restaurant item.
And here we, by the way,
see advantage of extracting this
into a separate partial that we can include.
It's super easy to now add it, such a restaurant item
without having to dig for the entire restaurants EJS file.
We just go to this item file
and we have all the code for such an item here.
And here I wanna change this link here, this button,
instead of linking to the website,
I wanna link to the restaurant itself
so to the detail page,
so save View Restaurant here,
and then on that detail page I wanna link to the website.
Now changing this button text is of course
only the first step.
The more important next step is
that we need such a detailed page
and we need a way of serving that detailed page.
So we need to add our service side code.
Now let's start by adding the detail page maybe,
for this I'll copy that restaurants.ejs file here
like this,
and I'll rename it to
restaurant-detail.ejs,
the name is up to you,
but this will be the page with the details
about a single restaurant
so I think the name makes sense.
I wanna have the general skeleton in there.
I wanna include my header and side drawer,
but in the main section I now wanna change the content.
I don't want to have a list of restaurants here
instead here in the h1 tech
I'd like to have to title of the restaurant.
And then below that I'd like to have my restaurant data.
So a paragraph with the Cuisine, let's say,
and the then maybe such a pipe symbol here
where I then have the Address there after,
and then a paragraph with the Description of the restaurant,
and then below that maybe a paragraph
with that link to the website,
View Website.
That is the general structure I wanna have here.
Now we can work on the styling and the concrete code
for outputting concrete data here later,
but that will roughly be my detail page.
Now we need a way of serving that detail page.
And that actually requires the use of a brand new concept,
which we haven't seen before.
We need dynamic routes.
Now, what are dynamic routes and why do we need them?
Well, we have a varying amount of restaurants here
and new restaurants can be added all the time.
So our restaurants are dynamic user generated data
and therefore as a developer, we don't know in advance,
how many restaurants we'll have.
Therefore every restaurant should have a unique identifier,
some unique id,
and then it would be great
if we could use one of the same page,
this template which we prepared here
with different data for different restaurants,
it's the same page, but the data differs
and we don't wanna create tens,
or dozens, or hundreds of routes here.
But instead we want to define one route
in our Express code here
which has some dynamic segment in the path, you could say,
because as I said as a developer
we don't know in advance
how many restaurants we'll have
so what we can't do is create
a bunch of paths like restaurant one,
and then another one for restaurant two,
that won't work.
We can't predict the number of restaurants in advance,
and we don't know de unique ids of all those restaurants
in advance.
So we'll need a way of defining a route
here in our Express code
that has a dynamic placeholder in the path
where we can then use
the concrete data entered in the URL
to load the correct restaurant.
And if that's not 100% clear yet,
I'll show it to you how that works and what I mean.
And for that let's, first of all,
maybe start with the kind of URL we'd like to visit.
Where should this button, this view restaurant button,
which it is soon lead to.
It should lead to something
like our domain/restaurants
and then the id of the restaurant
like r1, r2, r3 and so on.
And therefore I wanna define such a path,
such a route here at my backend,
the exact position doesn't matter,
but I'll do it all after the restaurants route
since this route, which we are about to define,
is kind of related to that.
For that I'll add another get route
because we wanna get a page,
we don't wanna submit to any data,
and now the path should be /restaurants,
but not just that,
instead it should be slash
and then the id of the restaurant,
but as mentioned we don't know the id in advance
and there will be dozens or hundreds of ids eventually.
That's why in Express you can define
a dynamic route with a dynamic placeholder
for some data that will be encoded in the URL
by adding a colon here in your path.
Let me zoom in a bit.
So we have this colon here in our path,
and then after this colon,
you can define any identifier
or placeholder name of your choice
like restaurantid
or just id,
now this is up to you, the colon is not.
Now, this defines a dynamic route
and then just as in all the other routes,
we have our Request Response Handler function here,
which I pass as a second argument to this get method here
and in there we can now do what we always do,
but, and that's new,
we will also get access to the concrete value
that was entered for id
so that if a user enters this page
for domain/restaurants/r1
we get access to this concrete r1 value
here inside of this handler function.
And we can then look for a restaurant with that id
to load and to display the data
for this specific restaurant.
That's how such dynamic routes work
and dynamic routes are a crucial feature of most websites
since most websites don't just have lists of data,
but instead also detail pages for data
like the details about a product you selected on Amazon,
where you get some unique identifier and coded into URL,
and you then want to load the details for this product
or in this case restaurant.
So that is a key feature
which we also need to build realistic websites
and this is how we can use it.
Now to get hold of the concrete value
that was entered by the user when this page is visited,
we can use this request object
and there we have a params key which we can access.
Params itself actually contains an object
and that object will then have any dynamic placeholders
that we defined in this path as properties, as keys.
So we have the id key here on params
because I chose id here in the URL.
If I chose rid here for restaurant id,
we have rid here as well.
So I'm going with id and then from here,
I get my restaurant id by extracting it
from req.params.id.
And now we can use this restaurant id that we got here
to load a specific restaurant
by its id from our restaurant data,
from that restaurants.json file.
And that's not a tiny problem
because at the moment our restaurants here
don't have any ids so we'll need to do that.
Before we do that though,
I wanna finish this dynamic route topic
and show you that it actually works
before we then as a next step,
also make sure that we can work with the data correctly.
And to show you that it works,
I wanna work on this dynamic route that we added
and then rendered this new view that we prepared
the restaurant-detail view
because we added the this restaurant detail EJS file.
And to this view,
I simply wanna pass my restaurant id
and I'll give it a key of rid
and then pass my extracted restaurant id
as a value to this rid key here,
which as you learned will be available
as a variable inside of that template therefore
because we're passing it with that second argument
to the render method
and the data we provide here is available
in the template then.
And therefore now in that template,
I will simply...
I'll put it here, let's say in the h1 tag,
there I'll output is rid value,
which should be that dynamic route parameter entered
in the URL.
And now in restaurant-item ejs
where I changed this button text,
I now also wanna change this link here
and that should no longer lead to the restaurant website,
but instead it should load a specific restaurant
and therefore here the path should be /restaurants/
and then the id of that restaurant
which at the moment is not data we have
so for the moment I'll just hard-code r1 as a value here,
but we'll change this later.
With all of that though,
we have some dummy codes to play around with.
And hence, if we now start our server again,
since I did stop it after the previous section,
if I reload this restaurant's page, the button changed
and if I click it, I am taken to that detail page.
The styling is missing, we'll have to fix this soon,
but I am taken to this detail page
and very important here
this id is being displayed
that's this value in the URL.
And if you changed that here,
if you enter anything else as an id, Something, for example,
then you see Something here.
Because with the code we wrote an app.js,
we accept this dynamic segment,
and then we get the concrete value that is provided
in the URL with that line of code.
And we can then use it for whatever we want.
At the moment the only thing we're using it for is
to then output it in the template.
Now, why are the styles missing?
The reason for that is that the path
to these style files have an issue
that we haven't encountered before, but now we do face it.
These are actually relative paths
here in restaurant-detail.ejs
but also in our head partial here,
I have relative paths,
as I explained in the previous core section,
if a path, no matter if it's to a different page
or to a resource like a CSS or JavaScript file,
does not start with a slash,
then it's a relative path, seen relative from the file
or from the path on the server
where this resource is requested.
Up to this point this wasn't a problem
because all these routes, which we had before,
all were only one level deep as it's called,
we had /nothings, /restaurants,
/recommend, and so on.
Now with that detail page for the restaurants
we have /restaurants/id,
now because of that, any resources requested
from that detail page are actually searched
inside of a /restaurants folder.
And you can see that if you open the developer tools
on this page where the request fails.
There you'll see a couple of error messages in the console,
and whilst they might sound cryptic,
you can see that the problem actually is the path
where it's looking for shared CSS.
It's looking for shared CSS in a styles folder,
in a restaurant's folder.
And the reason for that is that that detail page,
that path is appended after /restaurants.
So we have a nested path here, as it's called,
because we have /restaurants/ something else
before we only had one level /something
and then nothing else.
Now here we have two levels,
two slashes.
And therefore it's looking for the styles folder
in the restaurants folder which doesn't exist.
Now, the solution is easy though,
in head.ejs we should just switch to absolute paths
and therefore target /styles/shared,
and also /scripts/responsive
and do the same in the restaurant-detail.ejs file
and there target /styles/restaurants.
With that it's not trying to add that
as a relative path on the currently active path in the URL,
but instead it will always appended directly after the
domain itself.
And therefore if you make those changes
and we save everything,
if we reload, the styling is back
on that detail page as well.
So that's working and now with that,
we have our first dynamic route in place.
I hope it's clear why this feature exists
and which problem it solves
because we can now visit different restaurants
with different identifiers
and still show the same page with different data
and therefore, we can now actually work on our code
and make sure that our restaurants do have ids,
which we can use in this dynamic route.