Now in the last lesson we looked at how we can run code inside our EJS templates. 1
Now in this lesson I want to continue building out the functionality of what is our main goal right? 2
Making a To Do list app. 3
So inside our App.js wouldn't it be great if we didn't have to use this massive Switch statement to 4
convert this day from 0, 1, 2, 3 into the actual name say Sunday, Monday, Tuesday. Wouldn't it be great if we could 5
just use Javascript to do that? 6
Well let's see if it's possible. 7
So if you go into Google and we search for something for example Javascript date format, then if you 8
take a look at this highly relevant Stack Overflow post which says, 'How can I format a Javascript date 9
to print in a specific way' 10
then you can see that there's a whole bunch of answers and the accepted answer actually has this part 11
where it says this answer was written in 2010. 12
And there's better answers below and that better answer is actually this one. 13
There's a method called toLocaleDateString that allows you to format your Javascript using whichever 14
format you wish. 15
So for example you can include a day as numeric or 2-digit, 16
then you can have a weekday day which which can be narrow, short or long. 17
And you can have it for different languages. 18
So if you take a look at their example, they've created this variable called options which has a number 19
of properties. 20
So weekday is set as long, 21
year is set as numeric, month is long, day is numeric then they've created a new date and they've called 22
this method on that date rendering it in a US English format which looks like this without the options 23
and with the options included 24
it looks like this. 25
So this is pretty much what we want. 26
And so we're going to borrow this and add it to our code. 27
So firstly we have to create our options, 28
and this is going to be a Javascript object. 29
And in our date I want to have a weekday to begin with. 30
And my weekday, the option I'm going to set is going to be long. 31
I want to write out the entire day of the week. Weekday which is going to be long and the next thing 32
is the day which is going to be numeric and finally we're going to add that month which is going to 33
be long as well. 34
So now we have our options object. 35
We're going to use it to render our date. 36
So let's create a var day. 37
And this is going to be equal to today.toLocaleDateString and you can see that this converts 38
a date to a string returning the date portion using the operating systems locales conventions and of 39
course that means that you have to add in the locale which is basically a region. 40
And we're going to use something like English US, 41
so en-US and if you want that date string to be rendered in Japanese or Chinese, then you can 42
change that to the relevant locale. 43
So en-US and then we're going to pass in our options to format that date string. 44
So now if we hit save then this formatted day gets passed in here which gets sent over to our list. 45
ejs as a variable called kindOfDay. 46
And now to clear this part up as well 47
instead of having this code that checks for the kind of day, I'm going to have a really simple h1 that 48
just logs that date string inside an h1. 49
So I'm just going to put kindOfDay inside this tag. 50
So now if we hit refresh then you can see that we get our formatted string 51
Thursday June the 7th. 52
And now that we've tidied up our code a little bit, we can get on with building out the rest of our 53
to do list. 54
So the simplest form of our to do list is simply an unordered list with a bunch of list items. 55
So this will generate us a bunch of bullet points with each of our to do list items. 56
So first one will be buy food, 57
then you have one called-- 58
then of course you have to cook the food. 59
And my favorite part which is eat the food. 60
Now look at the clock 61
it's almost lunchtime. 62
And guess what I'm thinking about? 63
So this if we hit save will render a web page as a bunch of bullet points. 64
So now we want to be up to add new items to this list and in order to do that, we need to pass data back 65
from our web page to our server. And how have we been doing that so far? Post requests of course. 66
So as a challenge I want you to create a new form inside your list.ejs just as you have been doing 67
before inside your index.htmls. 68
And this form is going to have a single text input that is going to take whatever value the user puts 69
in there as the next to do list item. And then when you hit the submit button it's going to make a post 70
request to the home route. 71
So to complete the first part of the challenge, I just want you to create the form that is going to make 72
the post request inside our list.ejs in the same way that you have been doing it before inside your 73
other HTML pages. 74
So pause the video and give that a go. 75
All right so we start off by creating a new form and I'm going to keep the class empty for now. 76
And I'm going to change the action to our home run which is that forward slash or also known as the 77
root route. But I find root route 78
a bit of a tongue twister so I'm going to continue calling it the home route. But I'm sure you understand 79
what I'm talking about. 80
So the method I'm going to keep as post which is going to post the information that's inside my form 81
to my server at the home route. 82
So now inside the form we're going to add a single input that is going to have type text and the name 83
of this input 84
we'll just call it newItem. And I'm going to delete the value because the value is going to be whatever 85
the user inputs into that textfield. 86
And finally I need to add a button which has a type of a submit so that it will trigger this post request 87
in the form to this route and the name I'm going to keep as button but the button is going to have 88
a title of add. 89
So now if we hit save and we refresh our page we've now got an input where I can put in anything I want 90
and when I press add of course nothing happens. And we get this error saying, 'Cannot POST' to the home 91
route. 92
And that is because we have yet to write the code in our server to handle that post request. 93
So you know what's coming, 94
there's another challenge. 95
So inside your App.js, I want you to write some code that handles the post request to the home route 96
and just console log the text that the user wrote into that input. 97
So pause the video and see if you can complete this challenge. All right. 98
So as always we start off by writing app.post to handle post requests that go to a particular route. 99
And the route 100
in this case that we want to handle is the one to the home route. 101
And when that does happen, we're going to trigger a callback with a request and a response. 102
And inside our callback we're going to grab the value of what's inside our text box. 103
So remember we gave our text box a name of newItem and that's equivalent to the name of a variable. 104
And we can tap into that value by tapping into request.body.newItem. 105
But before we can use this thing called body, we of course have to set up body-parser. 106
Now you can write this anywhere below where 107
we create our app, but I'm just going to add it between the set and the get. 108
So I'm going to say app.use bodyParser.urlencoded. 109
And we're going to set the extended option as true. 110
Now it doesn't really matter if you set it as true or false 111
in our case but you do have to give it a value. 112
So now that we've told our app to use bodyParser, we can now grab the value of new item using this line 113
request.body.newItem. So we can either save this into a variable called item and then console log 114
it, or you can of course simply place this inside here and remove the need for that extra line. 115
So let's just review what happens when we press the submit button. Our form is going to make a post request 116
to the home route and it's going to post the value of our text input which has a name of newItem. 117
Now when that request is received, it gets caught inside this app.post section. And we tap into the 118
request 119
looking through the body of the post request and we search for the value of something called newItem. 120
So this has to match up with the name of our input in order to retrieve the value of that text input. 121
And then we log the value of item. 122
So let's hit save and let's try and give it a go. Go back to localhost:3000 and let's add a 123
new item, press add. 124
And now if we go into our hyperterminal you can see that the value of that text input gets logged inside 125
our console. 126
So brilliant. 127
That's now working. 128
So onto the next thing that we need to do. 129
So we've now passed the data from our web page to our server but we now need to pass the data back into 130
our web page namely into a new list item inside the ul. So we can start doing that by creating a new 131
list item and its content is going to be a EJS tag that is going to render a new list item. 132
So now we just have to pass in that new list item. 133
Now some of you might think that you could do it inside the post request. 134
So for example you could say res.render just as we did up here and we render our list template and 135
we pass in our item. 136
So remember the variable name was called newListItem 137
so I'm just going to copy it and put it in here as the key. And then the value is going to be equal to the 138
value of our variable item. 139
So I'm just going to write that inside here. 140
So we're going to render the list template and we're going to pass in this. 141
Now there's a bit of a problem here because right now if you save everything, you save the App.js and 142
your list.js and you try to refresh this page you will get a error. And it tells you that inside 143
your list.ejs on line 17 144
there is a problem. And line 17 is where we are trying to render our newListItem. 145
And the problem is a newListItem is not defined. 146
This is because when we try to go to localhost:3000 i.e. our home route, then we land inside this block 147
of code. And you can see that when we're trying to render list we're only passing in the value for this 148
variable kindOfDay and we're not passing in anything for newListItem. 149
So when it tries to render a list at this point then it doesn't actually have a value to put into this 150
new list item EJS tag. 151
And that is why our app crashes. 152
So we now know that every single time you try to render a list we have to provide both variables that 153
we want to render. 154
So to fix this then we would probably want to add our newListItem over to this res.render and we're 155
going to call it exactly the same as what we have in our template page which is newListItem and we're 156
going to pass in the value of this item that we've got over here. And inside our post request instead 157
of trying to res.render, we're simply going to say res.redirect. And we're going to re 158
direct to our home route. 159
So what this does is when a post request is triggered on our home route, we'll save the value of new 160
item in that text box to a variable called item and it will redirect to the home route which then 161
gets us over here and triggers the app.get for our home route. 162
And it will res.render the list template passing in both the kindOfDay as well as the newList 163
Item. 164
Now it's a little bit convoluted and it is quite roundabout. So you might have to play around with this 165
code in order to fully understand what's going on. 166
But we now have another problem. 167
So if I-- so if I hit save and I refresh our page you can see that it says that item is not defined. 168
And that's telling you that in your app.js on line 169
26, item is not defined. 170
So on this line at this point it can't access this variable called item because item was created inside 171
the post route. 172
In fact item only exists when we make a post request to our server. 173
So once the users type something into that text box do we actually create this variable called item. 174
If we try to pass it in here when it doesn't exist, that's why we get this particular error. And this 175
problem is related to something that we call scope in programming. And in the next lesson we're going 176
to be exploring scope in more detail. 177
But let me show you how you can fix this. Instead of having our variable created over here 178
we can create our variable at the top of our file. 179
So let's create this item variable and let's set it to equal nothing. 180
So a empty string. 181
And when we do receive a post request then we reset the item variable to whatever it is that the user 182
typed into the text box. 183
So for some of you guys you might have spotted that if we write a code like this we'll have a bit of 184
a problem because whenever we create a new post request then we replace the value of this item variable 185
and this li becomes the latest item. 186
So let me show you what I mean. 187
So you can see the last item in our list is ;Eat more food.' If I add another one 188
say Another and I hit add, 189
then it replaces our last item instead of what we want which is to add another li below the previous 190
one. 191
So essentially our code at the moment only lets us store one piece of data under this variable called 192
item and the old ones will get overwritten. 193
So what we need is to store our items in a collection. 194
So let's create an array. 195
So instead of having our variable being item, let's call items. 196
And this is now going to be a array and it's going to start out being empty but every single time we 197
get a new post request and we create a new variable called item, then we can append that item to our 198
array called items. 199
So items.push and the object we want to push is the new item that we got from our post request. 200
And when we pass it over to render our list view, then we're going to pass over our entire array. 201
So now if we hit save and refresh, you can see that we have a new problem. Instead of creating new lis 202
we're simply just rendering our array inside the single li. 203
And that's because if we have a look inside our list. 204
ejs, 205
all it's doing is just planting whatever it is that we got sent over inside this list item element. 206
And so if newListItem happens to be an array then all of that just gets put in here and rendered as 207
a single list item which is not what we want. 208
We want them to be all separate list items and we want to create new lis for every single new item 209
we add to our list. 210
So what we would need to happen is when we pass over an array or a collection like this, we want to loop 211
through it and create a new li for each item inside the array. 212
So essentially we would need to create a FOR loop. 213
So here's a challenge. 214
I want you to replace this line of code with a FOR loop using the EJS snippets that we learned 215
about in the last lesson so that we can loop through all of the items in the array and we're going to 216
create a single li that contains every single item inside this array. 217
So by the end of it you should be able to add new lis every single time you type a new to do list 218
item. 219
All right so let's give this a go. 220
Let's comment this line out and in it's place we're going to write a FOR loop. 221
So if we're going to create a new traditional FOR loop then we're going to create a variable called 222
i that's going to start off being equal to zero. 223
And it's going to run while i is less than the newListItem array.length. 224
And finally i is going to be incremented by 1 each time. 225
And at this point it's probably a good idea to change the name of this to reflect the fact that it's 226
now an array. 227
It's not a single item anymore. 228
So let's go ahead and change this to newListItems. 229
And remember that means we have to change it here as well. 230
And now we're going to create an li that is going to be newListItems at the index of i. 231
So these lines of code loops through our array 232
and for however many items there are in there, we're going to create a list item for each of them. 233
So remember in order to run code inside our EJS file we of course have to add the snippets tag on 234
each line where we have some code. 235
And inside the li we're going to render the value of newListItems at index i. 236
So we're going to use a slightly different tag which is the one that is a angled bracket, percentage 237
sign, equals in order to get the value of a newListItem at index i. 238
So let's delete our previous line of code and let's refresh our page. 239
And now if I add a new item then you can see that for every single new item I have it will get added 240
in to our ul and each item gets its own li. 241
Now we can make our code even more succinct by simply deleting all of these lis. 242
And instead we simply add it to our array. 243
So our array starts off with three items, buy food, cook food and eat food, and all three items inside the 244
items array will get loaded up into its own li 245
as soon as we load up the page. And when we add new items then it will get added to the end of the list. 246
So now our FOR loop takes care of rendering everything into a new li and it renders every single item 247
that we add into our items array. 248
So to summarize when we first load up our home page, we go through this route and we render our list 249
.ejs passing in two variables: one called kindOfDay and another called newListItems. 250
Now newListItems is set to equal the items array which starts off containing three strings, buy foo, 251
cook food, 252
eat food. 253
And this gets passed into the list.ejs under this variable name newListItems. 254
And over here we have a for loop that loops through the entire length of the newListItems array and 255
it renders a new LI for each item inside the array. 256
Now when a user adds a new item through the text input then that gets saved under the variable name 257
newItem and we trigger a post request to the home route which will be caught by this block of code. 258
And when we're inside this block of code we grab hold of the value of the newItem, 259
so whatever it is that the user typed inside here, 260
and then we save it to a variable called item and we add that item to our array called items. And then 261
we redirect to the home route. 262
So now we go back over here 263
but the items array has now increased by a size of one and our new item get pushed onto the end of the 264
array. 265
And now we're able to go ahead and render list again and pass over the now updated array with all 266
of our list items. 267
So this is a really fundamental part of templating and that is passing data through from the server 268
to our template and populating it with dynamic content. 269
So if this is at all confusing I recommend trying it yourself. 270
So trying to build the website as we have it right now by yourself without watching the videos. 271
So it might take a couple of gos and you might have to come back to the videos to refresh yourself 272
and remind yourself of how things are done 273
but this requires a little bit of repetition on your part and playing around with the code passing in 274
different things, looping through it, or using IF statements, using FOR statements on the EJS side 275
and rendering it inside the template. 276
But after you're done, in the next lesson we're going to talk about a concept in programming known as 277
scope. 278
So for all of that and more, I'll see you on the next lesson.