Now, with Express installed,
let's finally get to the point
to write more useful server-side code
and do something we couldn't do before.
Because just outputting a date snapshot,
we could have done that
with browser-side JavaScript as well.
We could have manipulated the DOM
and just output the current date snapshot there.
But now I wanna output a form
where users can enter some data, let's say simply a name,
and then I wanna store that data
in a file on my server, so on this remote machine,
a file not accessible by my clients, by my users therefore,
because it's stored on my machine,
and I then, as a last step, also want to set up a route,
so a path that we handle here,
where we list all the submitted names.
This might not be too useful as a website right now,
but it allows us to practice all these key functionalities
which we can then combine into a more useful example
in a second step.
And therefore, let's stick to this example here,
and let's say for just slash nothing,
instead of returning Hello World, I wanna return a form.
Now, we might in reality return a correct HTML skeleton here
with the DOCTYPE and the HTML element and so on,
but for the moment I'll just return the form
and let the browser add those missing elements.
We will soon get back to better HTML structures,
and we will soon get back to HTML files again,
but for the moment,
let's stick to this string-based, simple HTML content.
Now, in this form, I will add a label, a label element,
and we don't get out a completion here,
so make sure you don't introduce any typos,
and I'll say Your Name.
And then after this label,
I'll add the input element of type text
where the user should then enter his or her name.
Now, we could improve this with styling.
We should normally add an id here.
But for demo purposes, since this is all in one string
and therefore already a bit hard to read,
I'll keep this very short and concise,
and just add the bare minimum.
With that, if you save this file,
and you restart your server,
if you go back to just slash nothing,
you see this form here.
As a side note, if you did not stop your server before,
if it was already running, and you reload it,
you might not see that updated element.
You might not see that form.
The reason for that
is that whenever you change your Node.js code,
you need to quit your running server,
which was started based on the old code, and restart it.
Otherwise, you won't see your latest changes.
This can be a bit cumbersome and annoying,
and we'll find a workaround for that soon,
but for the moment we'll just keep on stopping
and restarting whenever we change and save our code.
Now, I'll keep that open here, just shrink this a bit
so that we still have that running server here,
we can now continue our work
because the idea now is that that form gets submittable.
For this, I'll also add a button here
with the button element, opening and closing tags,
where I say Submit as a caption.
And now you learned in that Forms course section
that such a button by default will submit the form
in which it sits,
and hence on this form, on this form element,
we can define the path the request should be sent to
and the method that should be used for that request.
If that's brand new to you,
definitely go back to that Forms section
because I do talk about it there.
And here I now can set the path
by adding the action attribute with double quotes,
and I wanna set this to store-user.
Now, this path is up to you, but I'll choose store-user,
and I'll set the method to POST here,
all caps between double quotes.
The alternative would be GET,
and we could make both approaches work,
but the default is to use a POST method
for sending data from the browser to the server
if the server should then store that data.
Now, what actually happens will depend
on the server-side code you write,
and that's what we'll do next,
but the convention is to use POST
if you wanna indicate that the data that is submitted
should be stored on the server.
And that is what I wanna achieve here,
so I will go for POST.
And now with that, we have a way
of submitting the form and sending such a request.
As a next step,
we need a way of handling a POST request to this path.
And at the moment, we only have two handlers
for GET requests to these paths here.
So we need to add a brand new handler.
Doesn't matter where you add it,
in front of the other handlers or after it.
Here I'll add it after the other handlers,
and now we don't need get but post.
Express.js offers different methods on this app object
for different kinds of HTTP requests that can be sent.
And thus far, we handled GET requests.
Now, with post, we'll handle a POST request.
Now, still as a first argument, as a first-parameter value,
we now define the path that should be used,
and here that's store-user
because that's the path I'm defining here.
So you should make sure that these paths are equal.
Then, again, the second parameter is a handler function
which works just as before, with request and response.
And now we still also want to send back a response,
but I now also wanna extract the data that's submitted
because that's the great thing about this form HTML element.
When used in a browser with the POST method,
once this form is submitted,
the browser will automatically send a POST HTTP request
to this path on the current URL,
and it will take all the fields that are in the form
and add them as data to that outgoing request.
The only addition we need to make to this input element
to make that work
is an extra attribute which should be called name,
and here I'll then choose username as a name.
This will then give us a key which we can use
to extract the data inserted into this input.
Otherwise, that input data would not be submitted.
But with that name set, it will be submitted,
and we will be able to use this username name,
which it shows here, to extract the data.
And therefore, now here in this function,
we can now use request body, a special property
which is exposed on this incoming request object by Express,
to get access to the data that was attached to the request,
and in case if a POST request will have that data,
and on body we can then, again, use the dot notation
to access different fields.
Body will basically be a JavaScript object
where keys that we chose here with that name attribute
will be properties on that object.
And the values of those properties
will be the values entered by the user,
in this case the username entered by the user.
So on request body, we can access .username
since we chose username as a name on our input.
And we can store that in a new constant,
maybe named username,
and that will then be the data the user entered.
Now, storing it in a file will be the next step.
For the moment, I just wanna console.log username here
and then also send back a response.
For that, we can use the response again,
and before, we used send to send back a response.
So I'll do that here again
and maybe just again create a h1 element
where we say Username stored
as a success message.
If we do all of that, we can try if that works.
For this, quit that running server with Control + C
since we changed the code,
and make sure that you save your code changes,
and then run this code, this app.js file again.
If we now reload localhost:3000,
we got this input form here with a button.
And if I now enter Max Schwarzmueller here,
and I submit this, you see this crashes.
You see we get an error here.
We also get this error here
in this command prompt where we started our server.
So something's going wrong here, and I'll quit the server
by running, by hitting Control + C again.
But what is the issue here?
Well, Express.js is a library
that mostly deals with routing incoming requests.
So it allows us to define which request to which path
with which method should be handled by which function.
That's what we're doing thus far.
Now, it also gives us easy access to request body,
but there is one crucial step
which it is not doing out of the box like that.
It's not parsing the actual request data.
It gets a request, and it might see that there is data,
but it's not translating that data
to such a JavaScript object automatically.
And here it might help to see
how that request actually looks like that's being sent.
For this, I'm back here in this form.
And if I now submit this again,
maybe with Manu entered here, doesn't matter,
and I do open my browser Developer Tools here in Chrome,
and I do go to the Network tab here,
so this is the tab we wanna go to, then if I click Submit,
you see one failing request down there, the red request.
Here you basically see
all the network requests your site is making.
And here you see one failing request.
Now, you can click on that request to learn more about it,
and you see, for example, the Response.
That was what we inspected before already.
But if you click on Headers,
you see some metadata about this request.
And here in this Headers area,
you see the Request Method: POST,
you see the Status Code sent back by the server,
and you see that here Node and Express
automatically send back 500 as a Status Code
since something went wrong on the server.
We had an error on the server,
and the application crashed here.
And if you scroll down,
you find the Request Headers and also the Request Data.
You can ignore the headers for now.
There are a bunch of headers here, a bunch of metadata
which was added automatically by your browser.
But as you scroll down further,
you find this Form Data part here at the very bottom,
and that is the extra data that was attached
to the request automatically by the browser
because it is a POST request sent
because a form was submitted.
And if you submit a form with the POST method,
which is what we are doing,
then the browser automatically reads
all the form inputs that have a name attribute
and adds their data to this request as so-called Form Data.
And the thing here is that this is not JavaScript code.
It might look kind of similar,
but this is really just some text
that's being attached to the request.
It's not JavaScript code, not a JavaScript object,
instead just some raw text
that needs to be parsed by the server
in order to use it there.
And that's the step that's missing here.
We are sending that request,
and we are ready to handle that request on our server side,
but we are not really parsing the request data
before we try to use it in JavaScript code.
And that's a missing step which we have to add here.
We have to tell Express that it should do that,
and thankfully that is fairly easy.
For this, at the top, right after we created the app object,
we should use it and use the use method.
Before, we saw get and post.
Use also allows us to handle incoming requests,
but unlike get and post,
it simply doesn't care about the kind of request that it is.
It will be applied to all requests.
And hence we also don't necessarily need
to define a path here, though we could do that,
but instead we can also directly just add an extra handler
that should be executed on all incoming requests.
And such general handler functions
which apply to more than one type of request
are typically called middleware function
because they are in the middle
between Express seeing that request
and our code handling that request.
And here we need a middleware function
that will look if the request, the incoming request,
has any kind of data
and which will then extract that data.
Now, as a middleware, we will now use Express,
so not the app but Express itself,
and on that access to urlencoded method
which it actually is.
Now, urlencoded is a method that will set up a body parser,
so a incoming request data parser,
that will look at all the incoming requests.
And if they carry form data,
that's what urlencoded will look for,
it will parse that included data
and translate it into a JavaScript object.
Now, the only thing we should also do here
is, to urlencoded, to this method, we should pass
a JavaScript object as an argument
and set extended equal to false here.
This option doesn't matter too much right now,
but we should explicitly set it to avoid getting warnings.
And once you did all of that,
you can open up your command line again
and now execute this server file again, app.js,
and then go back to just localhost:3000/,
and again enter your name like Max Schwarzmueller,
and click Submit.
And now you should get Username stored! here
and the URL changed to /store-user.
The reason for that
is that this request was sent automatically.
Also here, in the command line where you started the server,
you see that console.log output from this line here
where we are logging the username.
So here we see that the incoming data
was extracted correctly and is being output correctly.
If you wanna try this again,
reloading this page won't do the trick.
Indeed, you would get a warning
which you might have seen before
on other pages as well from time to time
because that is a URL that was only loaded
because a POST request was sent.
Whenever you enter something
in the address bar of a browser,
or you click the Reload icon,
you actually do send a GET request,
and the browser actually recognizes that this page
was originally loaded through a POST request
and hence warns you if you maybe want to send
a POST request again
and therefore submit the old form data again.
That's what this error tells you.
Here I don't wanna do that,
so I will cancel and instead manually go back to just /.
And then you could enter the data again or a different name,
submit it again, and you would again see the output here.
So now we are parsing that data successfully.
Now we also wanna store it and then use that stored data
to return a dynamic HTML page
to the visitors of our website.
For the moment, I'll just quit that server again.