Hey, guys.
In the last lesson we looked at how we can use the different types of EJS tags and to use it to run code
in our EJS templates.
In this lesson, we're going to dive a little bit deeper into passing data with EJS.
So from server to client side and from client to server side.
We've already seen passing data from server to the EJS file.
This is probably one of the simplest examples.
We do this using the res.render method and then we pass in firstly the name of the EJS file we want
to be rendered and then any sort of data that we want to render.
So this data has a property value which can then be picked up inside the EJS file and inserted using
the output EJS tag.
So then when this is actually rendered, we will get an h1 that says, "Hello Angela" and this data gets
pulled from here and inserted right into the placeholder.
We also saw how we can pass over more complex bits of data, for example, an actual array, and this
can simply be done by giving the data a name that can be accessed on the EJS side, and then the actual piece
of data to be sent over.
And then in our EJS file, we can pick up that array by the name that it was passed over as,
and then you saw how we could use a for loop or a forEach loop in order to tap into each of the items
in the array and render it into the EJS file. Ending up with something like this.
What happens if there actually is no data on the EJS side? Here,
take a look at this code.
We're expecting an array called fruit that we can loop through, but if we check on the index.js,
we render the index.ejs file, but we forgot to pass over any data.
This can happen quite frequently,
either the data is corrupted or there's some sort of bug in our code on our JavaScript side where we
don't actually send over what our EJS file expects.
Well, in JavaScript, normally you can prevent this situation and catch it by simply using an if statement.
You can say, "if this thing called fruit actually exists and is not undefined, then go ahead and run
the next bits of code."
Now you might think this would work, but unfortunately with EJS it does not.
This will actually crash our website and it won't render anything at all.
Now, what is the reason for this?
Well, the reason is because it's looking at this variable called fruits,
but in EJS land, unlike in JavaScript, it doesn't scope this variable.
What that means is it doesn't actually check to see, well, does this actually exist before it tries
to use it.
Instead it tries to use it and, "Oh, there's nothing.
It doesn't work.
Let's crash everything."
And this is one of the aspects of EJS as a templating language that you might not be used to if you're thinking
of it as just normal JavaScript.
So this is a good thing to be aware of.
So then what do we have to do to get around it?
Well, we can use this variable called, "locals".
What locals is, is basically a way to access all of the variables that get sent over with a
res.render.
Now you can also manually set res.locals and you can set it equal to some piece of data.
So you could say {data: 42} and that locals variable is what can be accessed in the rendered EJS file.
By simply using something like fruits, the name of the variable that gets passed over with the
res.render(),
essentially, what we're doing is we're using the shorthand of locals.name of variable.
This locals variable always exists and that means that we can always use it to check for the existence
of variables that are passed over to EJS,
and if this in fact does exist, then we can use it as we would normally.
This is just something that's quite important to be aware of when you're passing data from the server
to the EJS side.
Now, what about the opposite direction?
What if we want to pass data from the EJS side or from the client side back to the server?
Let's say we have a form on our website that we want users to fill in.
We want them to put in their first name and their last name, and then we want to be able to handle
that data in our server to do something with it, or to store it,
or to check it, whatever it may be,
h ow do we pass data backwards?
And as you've seen in previous examples, the easiest way to do this is through a POST request.
So this then exists on the EJS side as a form which has a destination also called an action, the method
that is going to be a POST request.
And when the form gets submitted then these pieces of data are labeled under their name attributes.
So fName is going to be equal to whatever the user types in here, and lName will be equal to whatever
the user types in here.
And when they click on the okay button, this app.post() gets triggered and inside the req.body,
when we've got body-parser enabled, we can access these different pieces of data and that's how we
get data from the client to the server side using EJS. It's pretty similar to how we would do with
normal HTML.
Now it's time to try an exercise where you practice passing data back and forth between the server and
client side, client to server side using EJS templates.
Download the starting file from this current lesson, and extract it and then open it up inside VS Code.
As always, the first thing we're going to do is go ahead and install all the required dependencies.
So I'm just going to run, "npm i"
on this folder, we get our node modules installed and let's first take a look at the solution.
So let's use nodemon to run solution.js which will start up on localhost:3000 and you should see
something that looks like this.
So we've got an h1 asking you to enter your name.
So let me go ahead and enter my name.
Click
OK.
And then it tells me there are 8 letters in my name. So I can now try it with somebody else's name.
And our website basically counts the number of letters in a name.
This is what you're aiming to build and the rest of it I'm going to leave for you to figure out how
to do.
You're going to have to write some code in the app.get() in order to render the h1 in the body of your
EJS file.
And it could say something like Enter your name or whatever it is as an instruction,
and that happens when we don't have any data being passed over to the index.ejs,
but if we did have some data being passed over, namely the number of letters in the name, then we
want it to be an h1 that says, "There are 9 letters..." or how many letters "in your name."
So think about this carefully, because initially if I go ahead and quit my server and restart, there
won't be any data being passed over.
So my website doesn't yet know how many letters there are in the name.
So at this point, this will be the h1 that will be shown.
But as soon as I enter something into here, this data gets sent over to my server side.
My server is the one that works out how many letters there are in that name and then passes that number
back over to EJS so that we render a different h1, inserting that number into here.
Have a think about how you would complete this challenge, break down the problem and using what you've
learned so far in this module, complete this challenge yourself. Pause the video now.
All right.
So let's run through the solution together and hopefully you've already gone part of the way or the
entire way to solving this.
So the first thing we want to happen, is to have an h1 that says "Write your name below," and you can insert
some emojis or you can copy and paste it from the Internet, whatever it is you want to do.
And once we've got that h1, then we can figure out how to render this EJS from our index.js.
So that's of course going to be in the GET route
and so we can use our res.render and then the name of our file is index.ejs. Let's hit Save. Let's
go ahead and quit out of our server that was running our solution.
Now let's use Nodemon and run index.js.
Now let's refresh and you can see we've got this working. At the moment,
this form is not really connected to anything.
So when we hit, Okay, even though there is a POST route here, it doesn't send anything back,
so our website actually just hangs until the browser decides to kill it.
So let's write something in here to handle the data that gets sent over.
Now notice I've already inserted the body-parser code so you can use body-parser,
you don't have to write all of this extra code.
But remember when you're writing this website from scratch yourself, you need the body-parser middleware
in order to be able to access the body of the POST requests.
So now we can say req.body and we want to tap into the two things that we get back from the
form.
One is called fName for the first name,
the next one is the lName for the last name,
and notice in this case, I don't actually have any labels for my inputs,
instead, I've just put a placeholder which essentially will show up in the form.
So let's tap into the fName and the lName.
What I'm going to do is I'm going to create a new const, which is called numLetters, and
I'm going to set it to req.body.fName.length
which gives me the length of that string and I'm going to add the length to req.body and get
hold lName and also use .length.
This is simplified code that we could have probably written out in 3 or 4 lines depending on how comfortable
you feel with JavaScript.
You can split this out if you wish and you can consolelog() each of the different parts. You can console.log()
req.body.
You can console.log() req.body["fName"].
You can create a variable for the length of the first name.
You can create a variable for the length of the surname, add it all together,
but essentially this is the final logic.
Let's go ahead and console.log() the numberOfLetters.
So if we go back Refresh, let's test it with my name.
Click.
OK.
So then we go and take a look at our terminal and you see number 8 being printed out.
Now, if you get some weird errors or it doesn't work, try restarting the server.
Sometimes what happens is you enter the form on a non-updated version of your localhost:3000, so you
can try refreshing the website, going to the URL or simply restarting the server.
But either way, with these lines of code you should be able to console.log() the number of letters that's
being entered into the form.
And then the all-important thing is we need to send this variable back over to our EJS.
So let's go ahead and use the res.render() and we want to render our index.ejs and we want to pass
over this numberOfLetters as a variable,
and this is the value that's going to be passed over.
Now we can pick up that variable in our index.ejs.
So remember what it is that we called it, and we can put it into an h1.
So essentially we'll have two different h1's,
if we don't have that variable, numberOfLetters, then we want this h1 to show up,
but if we did, then we want this h1 to show up.
So we'll need some sort of if-statement that can check to see if this exists,
and if it does, let's render the h1 where we say something like, "There are this numberOfLetters
in your name."
Of course, in order for this to be rendered as actual code, we need our EJS angle bracket, percentage,
equals (<%=), and then the closing bracket as well.
And also our code which we need to be evaluated but not necessarily outputted, needs to have the EJS brackets
around it.
So now if this variable exists, we want to show this h1, but otherwise, we want to show a different
h1 and that is going to be this h1.
So if we have this variable, then that means the form has already been completed and we can insert
the number of letters into the h1.
If we don't have that variable and it's empty, then that means the user must have accessed this website
for the first time and we want to give them some instructions as to what they should do.
Now, when I run this, it's going to break and you might already know why, but let's just test it
out.
Let's hit Save.
Let's go back to our website, refresh localhost:3000 and it crashes.
It tells us there's a ReferenceError and it says that on this line, there's a little pointy arrow here.
Line 12, numberOfLetters, is not defined.
So basically it tried to access numberOfLetters to know what to do with it,
and lo and behold, it doesn't exist because this is the first time the user is accessing the website
and they haven't yet entered a name for our server to work out the number of letters.
What we need to do is we need to change this to check for the locals variable to see if this thing actually
exists because we know this variable definitely always exists in EJS files, and if it does, then continue
with the code where we actually use it.
So let's hit Save. Let's go back, Refresh.
At the moment we know that numbeOfLetters doesn't exist, so we get this h1 but once we add in
our name and it gets calculated, then the different h1 gets rendered.
Did you manage to work this out?
If you didn't, be sure to take a look through the solution code and check your code and figure out
how you can fix your code to make it work, and see if you have any typos or see if you have any logic
errors.
But hopefully, by reviewing this lesson you will have understood how to pass data from the server side
into the client side via EJS templates, but also from the client side to the server side using EJS templates
as well.
In the next lesson, we're going to look at how we can use EJS in Layouts and in Partials so that we
can save ourselves from writing extra code when we have bits of our website that will repeat.
So for all of that and more, I'll see you there.