1
00:00:01,000 --> 00:00:04,226
So let's now hook up this View Post link

2
00:00:04,226 --> 00:00:07,601
and work on this post-detail page together.

3
00:00:07,601 --> 00:00:12,081
Let's start with the link in the post-item EJS file.

4
00:00:12,081 --> 00:00:13,645
It's this link here,

5
00:00:13,645 --> 00:00:16,364
and it should point at a new path,

6
00:00:16,364 --> 00:00:21,365
which could be posts/ and then a specific post ID.

7
00:00:21,549 --> 00:00:24,149
Now, of course, every post has a different ID.

8
00:00:24,149 --> 00:00:28,720
We can just output this by referring to post._id,

9
00:00:28,720 --> 00:00:29,553
as you learned.

10
00:00:29,553 --> 00:00:32,691
That's how we can refer to a specific post ID

11
00:00:32,691 --> 00:00:34,462
and output that here,

12
00:00:34,462 --> 00:00:37,330
so that different links are rendered

13
00:00:37,330 --> 00:00:39,040
for different post items.

14
00:00:39,040 --> 00:00:40,970
Here, we only have one post,

15
00:00:40,970 --> 00:00:43,239
but potentially we have more than one.

16
00:00:43,239 --> 00:00:45,490
And with that all ready,

17
00:00:45,490 --> 00:00:47,331
if you would save everything and reload,

18
00:00:47,331 --> 00:00:50,414
this link, if you look in the bottom left corner,

19
00:00:50,414 --> 00:00:51,900
it's very small,

20
00:00:51,900 --> 00:00:54,500
but there, you can see that the URL this is pointing

21
00:00:54,500 --> 00:00:57,623
at already includes the post ID.

22
00:00:58,900 --> 00:01:01,660
Now we just have to register a route for this

23
00:01:01,660 --> 00:01:05,033
and then render this post-detail EJS file.

24
00:01:06,378 --> 00:01:08,519
And for this, in blog.js,

25
00:01:08,519 --> 00:01:11,710
we can register that new route here,

26
00:01:11,710 --> 00:01:13,881
and that should be a get route

27
00:01:13,881 --> 00:01:18,270
because whenever you enter a URL or you click a link,

28
00:01:18,270 --> 00:01:20,009
a get request will be sent,

29
00:01:20,009 --> 00:01:25,009
and the URL path is posts/ and then the ID,

30
00:01:25,513 --> 00:01:27,865
which will be different for every post.

31
00:01:27,865 --> 00:01:31,326
Hence, this screams for a dynamic route

32
00:01:31,326 --> 00:01:33,977
where we simply have a placeholder

33
00:01:33,977 --> 00:01:36,388
which gives us access to the concrete value

34
00:01:36,388 --> 00:01:38,490
that's part of the URL

35
00:01:38,490 --> 00:01:43,254
whenever this function is executed here, like this.

36
00:01:43,254 --> 00:01:47,777
That's what we also did in the MySQL section.

37
00:01:47,777 --> 00:01:52,777
Now here, I now wanna use this ID to get the data,

38
00:01:52,780 --> 00:01:55,423
the post data, for a specific post.

39
00:01:56,345 --> 00:01:57,288
So for that,

40
00:01:57,288 --> 00:02:01,680
I'll get my post ID here by accessing req.params.id,

41
00:02:01,680 --> 00:02:05,480
.id because that's the identifier I chose there

42
00:02:05,480 --> 00:02:06,716
in my path here.

43
00:02:06,716 --> 00:02:11,716
And then, we can, again, use my database here to reach out

44
00:02:14,560 --> 00:02:16,716
to the posts collection,

45
00:02:16,716 --> 00:02:21,716
and then run the findOne method here.

46
00:02:21,853 --> 00:02:26,853
And findOne will find us the first matching document.

47
00:02:27,072 --> 00:02:30,646
Of course, that's an asynchronous operation as always,

48
00:02:30,646 --> 00:02:33,126
so we can add the async keyword here

49
00:02:33,126 --> 00:02:36,823
so that we can await this later.

50
00:02:37,880 --> 00:02:39,040
But before we await this,

51
00:02:39,040 --> 00:02:41,910
we need to write more code here

52
00:02:41,910 --> 00:02:43,954
to define which posts we wanna fetch.

53
00:02:43,954 --> 00:02:46,748
I don't wanna find the first post in general,

54
00:02:46,748 --> 00:02:50,683
but the first post that matches a certain condition.

55
00:02:50,683 --> 00:02:52,914
And we define that by passing an object

56
00:02:52,914 --> 00:02:55,316
as a first parameter value to findOne.

57
00:02:55,316 --> 00:02:57,960
And here, I'm then looking for the post

58
00:02:57,960 --> 00:03:01,993
where _id is equal to my postId here.

59
00:03:03,300 --> 00:03:08,180
Now, we can also transform this into an objectId first here,

60
00:03:08,180 --> 00:03:13,180
like this, so that we have this official objectId object

61
00:03:13,754 --> 00:03:16,011
MongoDB uses internally.

62
00:03:16,011 --> 00:03:17,000
And with that,

63
00:03:17,000 --> 00:03:19,360
we're then getting that post ID,

64
00:03:19,360 --> 00:03:21,343
or that post with that post ID.

65
00:03:22,346 --> 00:03:23,959
Now, the question is

66
00:03:23,959 --> 00:03:26,462
which kind of data do we need there then?

67
00:03:26,462 --> 00:03:28,271
Which kind of data do we want to fetch

68
00:03:28,271 --> 00:03:31,170
for the matching document?

69
00:03:31,170 --> 00:03:32,003
And for this, it's, again,

70
00:03:32,003 --> 00:03:36,328
worth having a look at our post-detail EJS file.

71
00:03:36,328 --> 00:03:39,005
There, I wanna output the title of the post,

72
00:03:39,005 --> 00:03:40,968
then some metadata.

73
00:03:40,968 --> 00:03:42,934
And I can tell you that there,

74
00:03:42,934 --> 00:03:46,809
I want the author name and the author email address

75
00:03:46,809 --> 00:03:49,153
and also the date of the post.

76
00:03:49,153 --> 00:03:51,631
And then here, I want the post body.

77
00:03:51,631 --> 00:03:56,631
What I don't need here is the post summary, for example.

78
00:03:56,774 --> 00:04:01,774
So what we can do here is, back in blog.js,

79
00:04:03,039 --> 00:04:05,980
we can add this projection object,

80
00:04:05,980 --> 00:04:10,980
this second parameter value, and simply exclude summary.

81
00:04:12,900 --> 00:04:14,129
If you exclude one field,

82
00:04:14,129 --> 00:04:17,588
all other fields are included by default.

83
00:04:17,588 --> 00:04:22,063
So this is how we can include all fields but summary.

84
00:04:23,030 --> 00:04:28,030
This will then give us this one matching post, like this.

85
00:04:28,307 --> 00:04:30,289
And of course, theoretically,

86
00:04:30,289 --> 00:04:33,707
we could have entered a URL manually

87
00:04:33,707 --> 00:04:35,766
with an ID that doesn't exist.

88
00:04:35,766 --> 00:04:39,960
So I first of all, wanna check if that succeeded or not,

89
00:04:39,960 --> 00:04:43,579
and I wanna check if post is undefined, if it's falsy.

90
00:04:43,579 --> 00:04:45,718
So if we don't have a post,

91
00:04:45,718 --> 00:04:50,718
then I actually want to return a response

92
00:04:50,958 --> 00:04:55,690
where I set the status code to 404 for Not Found

93
00:04:55,690 --> 00:05:00,313
and where I render this prepared 404 template like this.

94
00:05:02,113 --> 00:05:05,878
And I return here so that no other code executes

95
00:05:05,878 --> 00:05:08,156
in this route function.

96
00:05:08,156 --> 00:05:11,830
So that's the if check to handle the case

97
00:05:11,830 --> 00:05:13,343
that we did not find a post.

98
00:05:13,343 --> 00:05:15,779
If we did find a post, on the other hand,

99
00:05:15,779 --> 00:05:19,622
of course, I wanna render the post-detail EJS file.

100
00:05:19,622 --> 00:05:23,859
So then, I wanna render post-detail,

101
00:05:23,859 --> 00:05:28,859
so that is this EJS file here, and queue that file.

102
00:05:30,938 --> 00:05:33,340
I'll pass some data to this template.

103
00:05:33,340 --> 00:05:34,242
I'll pass some data.

104
00:05:34,242 --> 00:05:36,761
I'll pass my post data.

105
00:05:36,761 --> 00:05:39,540
That's the key exposed to the template.

106
00:05:39,540 --> 00:05:41,843
That's the value for that key.

107
00:05:42,743 --> 00:05:44,868
So now in that template,

108
00:05:44,868 --> 00:05:47,668
we should be able to use that post data.

109
00:05:47,668 --> 00:05:50,313
Here in post-detail,

110
00:05:51,180 --> 00:05:55,135
I will, first of all, output the post.title here.

111
00:05:55,135 --> 00:06:00,135
Down here, I'll output my post.body.

112
00:06:02,537 --> 00:06:04,591
And by the way, body,

113
00:06:04,591 --> 00:06:07,440
as mentioned in the MySQL section already,

114
00:06:07,440 --> 00:06:10,762
has a special style attached where we ensure

115
00:06:10,762 --> 00:06:15,660
that line wrapping, so line breaks in the post body inserted

116
00:06:15,660 --> 00:06:17,920
in the Create a Post text field,

117
00:06:17,920 --> 00:06:20,650
are preserved with this setting.

118
00:06:20,650 --> 00:06:23,076
I talk about this in the MySQL course section.

119
00:06:23,076 --> 00:06:26,116
It's a CSS setting that overwrites the default,

120
00:06:26,116 --> 00:06:29,754
where whitespace and line break would be ignored,

121
00:06:29,754 --> 00:06:31,853
and ensures that it's not ignored,

122
00:06:31,853 --> 00:06:33,754
but instead rendered on the screen

123
00:06:33,754 --> 00:06:36,930
so that if the user entered some line breaks

124
00:06:36,930 --> 00:06:38,954
in the text entered for a new post,

125
00:06:38,954 --> 00:06:41,809
those line breaks are preserved.

126
00:06:41,809 --> 00:06:43,570
That's just a side note.

127
00:06:43,570 --> 00:06:45,474
But that's the body then.

128
00:06:45,474 --> 00:06:47,755
And then, for the metadata,

129
00:06:47,755 --> 00:06:52,607
I actually wanna output two pieces of metadata here,

130
00:06:52,607 --> 00:06:55,552
and that's the author name and then the date.

131
00:06:55,552 --> 00:06:59,552
Now for the name, I'll use the address HTML element,

132
00:06:59,552 --> 00:07:02,874
which is a default standardized HTML element.

133
00:07:02,874 --> 00:07:05,568
And then, I'll add this pipe symbol.

134
00:07:05,568 --> 00:07:08,193
So this character on my keyboard.

135
00:07:08,193 --> 00:07:11,240
And then, I'll put the date time snapshot

136
00:07:11,240 --> 00:07:12,814
with the time HTML element,

137
00:07:12,814 --> 00:07:16,942
which is a another default, standardized HTML element.

138
00:07:16,942 --> 00:07:19,540
I did talk about these elements

139
00:07:19,540 --> 00:07:21,060
in the MySQL section already.

140
00:07:21,060 --> 00:07:23,519
These are built-in HTML elements,

141
00:07:23,519 --> 00:07:26,785
where address should be used for outputting some addresses.

142
00:07:26,785 --> 00:07:31,300
Not just in the sense of home or office addresses,

143
00:07:31,300 --> 00:07:32,708
but also email addresses,

144
00:07:32,708 --> 00:07:36,623
and times should be used for outputting timestamps.

145
00:07:37,673 --> 00:07:42,456
So here between address, I wanna output a link actually,

146
00:07:42,456 --> 00:07:45,741
which contains the name of the author.

147
00:07:45,741 --> 00:07:49,143
So here, we can output post.author.name,

148
00:07:50,760 --> 00:07:53,960
and the value here should be mailto:,

149
00:07:55,901 --> 00:07:57,730
mailto is an instruction

150
00:07:57,730 --> 00:07:59,768
which will automatically open the mail client

151
00:07:59,768 --> 00:08:03,397
on your computer if you click such a link,

152
00:08:03,397 --> 00:08:06,510
and then we just have to define the address

153
00:08:06,510 --> 00:08:08,717
to which that email should be sent.

154
00:08:08,717 --> 00:08:10,709
It's not sent automatically,

155
00:08:10,709 --> 00:08:14,257
but it will be pre-filled in that mail that opened up

156
00:08:14,257 --> 00:08:15,810
once you click that link.

157
00:08:15,810 --> 00:08:20,810
And here, that should be post.author.email here.

158
00:08:22,497 --> 00:08:26,287
So that will render such a link and the author name.

159
00:08:26,287 --> 00:08:28,860
And here, for the time, for the moment,

160
00:08:28,860 --> 00:08:33,727
I'll output post.date, but we'll come back to that later.

161
00:08:33,727 --> 00:08:38,669
And the time HTML element also wants a datetime attribute,

162
00:08:38,669 --> 00:08:40,200
which you should always set,

163
00:08:40,200 --> 00:08:41,780
which contains a machine-readable,

164
00:08:41,780 --> 00:08:44,907
a version of that datetime value.

165
00:08:44,907 --> 00:08:46,200
For the moment,

166
00:08:46,200 --> 00:08:50,655
I'll set the same value for both the visible content

167
00:08:50,655 --> 00:08:52,600
and the HTML attribute,

168
00:08:52,600 --> 00:08:55,437
but I'll revisit these values in a second.

169
00:08:55,437 --> 00:08:58,150
But for the moment, it's good enough,

170
00:08:58,150 --> 00:09:01,173
and we should be outputting the post data here now.

171
00:09:02,684 --> 00:09:05,239
If we, again, save everything,

172
00:09:05,239 --> 00:09:08,019
and we now click View Post,

173
00:09:08,019 --> 00:09:09,939
we should see something like this.

174
00:09:09,939 --> 00:09:12,931
And of course, the date is not formatted

175
00:09:12,931 --> 00:09:15,157
in the way I want it to be formatted,

176
00:09:15,157 --> 00:09:17,220
but the rest is looking good.

177
00:09:17,220 --> 00:09:18,815
And we can also click this link here,

178
00:09:18,815 --> 00:09:22,115
and this will open up a mail client for me here

179
00:09:22,115 --> 00:09:23,591
on a different screen,

180
00:09:23,591 --> 00:09:27,998
which has this address of the author already filled in

181
00:09:27,998 --> 00:09:31,113
as a target email address.

182
00:09:31,986 --> 00:09:34,337
So therefore, that's how we can fetch the data

183
00:09:34,337 --> 00:09:37,460
for a single post and how we can then output it.

184
00:09:37,460 --> 00:09:38,340
Now as a last step,

185
00:09:38,340 --> 00:09:41,973
I also wanna optimize this date here a little bit.

