So let's now hook up this View Post link
and work on this post-detail page together.
Let's start with the link in the post-item EJS file.
It's this link here,
and it should point at a new path,
which could be posts/ and then a specific post ID.
Now, of course, every post has a different ID.
We can just output this by referring to post._id,
as you learned.
That's how we can refer to a specific post ID
and output that here,
so that different links are rendered
for different post items.
Here, we only have one post,
but potentially we have more than one.
And with that all ready,
if you would save everything and reload,
this link, if you look in the bottom left corner,
it's very small,
but there, you can see that the URL this is pointing
at already includes the post ID.
Now we just have to register a route for this
and then render this post-detail EJS file.
And for this, in blog.js,
we can register that new route here,
and that should be a get route
because whenever you enter a URL or you click a link,
a get request will be sent,
and the URL path is posts/ and then the ID,
which will be different for every post.
Hence, this screams for a dynamic route
where we simply have a placeholder
which gives us access to the concrete value
that's part of the URL
whenever this function is executed here, like this.
That's what we also did in the MySQL section.
Now here, I now wanna use this ID to get the data,
the post data, for a specific post.
So for that,
I'll get my post ID here by accessing req.params.id,
.id because that's the identifier I chose there
in my path here.
And then, we can, again, use my database here to reach out
to the posts collection,
and then run the findOne method here.
And findOne will find us the first matching document.
Of course, that's an asynchronous operation as always,
so we can add the async keyword here
so that we can await this later.
But before we await this,
we need to write more code here
to define which posts we wanna fetch.
I don't wanna find the first post in general,
but the first post that matches a certain condition.
And we define that by passing an object
as a first parameter value to findOne.
And here, I'm then looking for the post
where _id is equal to my postId here.
Now, we can also transform this into an objectId first here,
like this, so that we have this official objectId object
MongoDB uses internally.
And with that,
we're then getting that post ID,
or that post with that post ID.
Now, the question is
which kind of data do we need there then?
Which kind of data do we want to fetch
for the matching document?
And for this, it's, again,
worth having a look at our post-detail EJS file.
There, I wanna output the title of the post,
then some metadata.
And I can tell you that there,
I want the author name and the author email address
and also the date of the post.
And then here, I want the post body.
What I don't need here is the post summary, for example.
So what we can do here is, back in blog.js,
we can add this projection object,
this second parameter value, and simply exclude summary.
If you exclude one field,
all other fields are included by default.
So this is how we can include all fields but summary.
This will then give us this one matching post, like this.
And of course, theoretically,
we could have entered a URL manually
with an ID that doesn't exist.
So I first of all, wanna check if that succeeded or not,
and I wanna check if post is undefined, if it's falsy.
So if we don't have a post,
then I actually want to return a response
where I set the status code to 404 for Not Found
and where I render this prepared 404 template like this.
And I return here so that no other code executes
in this route function.
So that's the if check to handle the case
that we did not find a post.
If we did find a post, on the other hand,
of course, I wanna render the post-detail EJS file.
So then, I wanna render post-detail,
so that is this EJS file here, and queue that file.
I'll pass some data to this template.
I'll pass some data.
I'll pass my post data.
That's the key exposed to the template.
That's the value for that key.
So now in that template,
we should be able to use that post data.
Here in post-detail,
I will, first of all, output the post.title here.
Down here, I'll output my post.body.
And by the way, body,
as mentioned in the MySQL section already,
has a special style attached where we ensure
that line wrapping, so line breaks in the post body inserted
in the Create a Post text field,
are preserved with this setting.
I talk about this in the MySQL course section.
It's a CSS setting that overwrites the default,
where whitespace and line break would be ignored,
and ensures that it's not ignored,
but instead rendered on the screen
so that if the user entered some line breaks
in the text entered for a new post,
those line breaks are preserved.
That's just a side note.
But that's the body then.
And then, for the metadata,
I actually wanna output two pieces of metadata here,
and that's the author name and then the date.
Now for the name, I'll use the address HTML element,
which is a default standardized HTML element.
And then, I'll add this pipe symbol.
So this character on my keyboard.
And then, I'll put the date time snapshot
with the time HTML element,
which is a another default, standardized HTML element.
I did talk about these elements
in the MySQL section already.
These are built-in HTML elements,
where address should be used for outputting some addresses.
Not just in the sense of home or office addresses,
but also email addresses,
and times should be used for outputting timestamps.
So here between address, I wanna output a link actually,
which contains the name of the author.
So here, we can output post.author.name,
and the value here should be mailto:,
mailto is an instruction
which will automatically open the mail client
on your computer if you click such a link,
and then we just have to define the address
to which that email should be sent.
It's not sent automatically,
but it will be pre-filled in that mail that opened up
once you click that link.
And here, that should be post.author.email here.
So that will render such a link and the author name.
And here, for the time, for the moment,
I'll output post.date, but we'll come back to that later.
And the time HTML element also wants a datetime attribute,
which you should always set,
which contains a machine-readable,
a version of that datetime value.
For the moment,
I'll set the same value for both the visible content
and the HTML attribute,
but I'll revisit these values in a second.
But for the moment, it's good enough,
and we should be outputting the post data here now.
If we, again, save everything,
and we now click View Post,
we should see something like this.
And of course, the date is not formatted
in the way I want it to be formatted,
but the rest is looking good.
And we can also click this link here,
and this will open up a mail client for me here
on a different screen,
which has this address of the author already filled in
as a target email address.
So therefore, that's how we can fetch the data
for a single post and how we can then output it.
Now as a last step,
I also wanna optimize this date here a little bit.