WittCode💻

Node and Express - Handling HTML Forms

By

Learn everything about Express in this Node and Express tutorial series. This article goes in depth on how to handle HTML forms with Express. We will also learn about the express.json and express.urlencoded middleware.

Table of Contents 📖

What is an HTML Form?

An HTML form is a group of one or more fields on a webpage used to collect information. It is typically submitted to a server as a POST request for processing. A common HTML form is a login form containing two inputs for username and password and a button for submitting the username and password to the server.

What is an HTTP POST Request?

An HTTP POST request is used to send data to a server, often to create a resource. The data that is sent to the server is stored in the body of the HTTP request. Below is an example of an HTTP POST request that sends json data to the login route on wittcode.com.

POST /login HTTP/1.1
Host: wittcode.com
Content-Type: application/json
Content-Length: 30

{"username": "WittCode", "password": "soccer"}

How to Create an HTML Form?

An HTML form is defined inside

tags. The HTML element is a container for different types of input. For example, the form could contain checkboxes, text fields, radio buttons, etc. The most commonly used HTML form element is . The element is used to get user input. The element can also be displayed in many different ways depending on the supplied type attribute. For example, type="radio" makes the input a radio button, type="checkbox" makes the input a checkbox, and so on.

Creating an HTML Form with Pug

We will create our HTML form using pug. Remember, pug code will be compiled into HTML by our server before being served. Place the following inside our views folder inside a file called login.pug.

doctype html
html
    head
    title Login
    link(rel='stylesheet' href='static/css/login.css')
    body
    #container
        form(action='/login' method='POST')
            h1 WittCode Login
            label Username:
            input(type='text' name='username')
            label Password:
            input(type='text' name='password')
            input(type='submit' value='Login')

Image

This simple form consists of two text fields and one submit button. The first text field has a label specifying it to be the username text field. The other text field has a label specifying it to be the password text field.

Form Action Attribute

The element's action attribute specifies where to send the form data when it is submitted. We want the information in the form to be sent to our login route so we specify action='/login'. Possible values for the action attribute are either a relative or absolute URL.

Form Method Attribute

The element's method attribute specifies how the data is sent. We want our form data to be sent as a POST request. This is why we specified method='POST' in our pug code.

Styling our Pug Form

As seen in the code below, we are using a CSS file to style our pug form.

link(rel='stylesheet' href='static/css/login.css')

Inside our public directory (which holds our static content) create a folder called css, create a file called login.css inside it, and place the following inside.

* {
    font-family: cursive;
}

body {
    height: 100vh;
    width: 100vw;
    display: flex;
    justify-content: center;
    margin: 0;
}

#container {
    display: flex;
    justify-content: center;
    align-items: center;
}

form {
    display: flex;
    justify-content: center;
    flex-direction: column;
    align-items: center;
    background-color: gainsboro;
    height: 400px;
    width: 400px;
    border-radius: 40px;
}

input:not([type='submit']) {
    width: 250px;
    height: 25px;
    border-radius: 5px;
    border: transparent;
    padding: 2px 0 2px 5px;
    margin: 10px 0;
}

input[type='submit'] {
    font-size: 1.2em;
    border: none;
    margin-top: 5px;
    border-radius: 5px;
}

Image

This CSS centers our form on the webpage, aligns the elements within the form, adds some color to the form, and a few other things.

Creating a Route to Display our Pug Form

Now, inside our routes folder, lets create a folder called login and place the following code inside an index.js file.

const express = require('express');
const router = express.Router();

router.get('/', (request, response) => {
    response.render('login');
});

module.exports = router;

Image

This route will send our pug form when it receives a GET request.

Registering our Express Router with our Express App

Don't forget to register this new Express router with our Express app by placing the following in our main index.js file.

const login = require('./routes/login');

app.use('/login', login);

Displaying our Pug Form

Now, if we navigate to localhost:1234/login we should see the following.

Image

Configuring Express to Handle Form Data

To handle form data with Express we need to make use of two middleware functions: express.json() and express.urlencoded(). Add the following to our main index.js file.

app.use(express.json());
app.use(express.urlencoded({ extended: true }));

It is very important to place these global middleware functions above where we registered our login router with our Express application. Remember, middleware functions are executed in order, so we want our JSON parsing middleware to be executed before we reach our POST route.

Why do we need these Middleware Functions?

We need the express.json() and express.urlencoded() middleware functions for POST requests. This is because POST request data is sent in the body of the request and we need a way to access it. These middleware functions allow us to access this data.

What is express.json()?

The middleware express.json() is a built-in Express middleware that parses POST requests with JSON data in their body. express.json() expects POST request data to be sent in JSON format such as below.

{
    "username": "WittCode",
    "password": "mypassword"
}

Specifically, express.json() parses requests where the Content-Type header is application/json. If there was no body to parse, the Content-Type was not matched, or an error occurred, then request.body will be an empty object.

What is the Content-Type Header?

Content-Type is an HTTP header that indicates the media type of the sent/received resource. For example, a GIF image would have a Content-Type of image/gif, an html file would have a Content-Type of text/html, and so on.

What is express.urlencoded({ extended: true })?

The middleware express.urlencoded() is a built-in Express middleware that parses POST requests with urlencoded payloads. express.urlencoded() expects POST request data to be sent as keys and values separated by a & and with a = between the key and value. An example is provided below.


username=WittCode&password=mypassword
    

Specifically, express.urlencoded() parses requests where the Content-Type header is application/x-www-form-urlencoded. express.urlencoded() also accepts a configuration object as an argument. One of the configuration options is extended which is false by default. Setting extended to true allows for objects and arrays to be encoded in the URL-encoded format. This makes working with url-encoded data similar to working with JSON.

Creating a POST Route

Lets go back into routes/login/index.js and create a route that will work with the POST data sent from our pug form.

router.post('/', (request, response) => {
    response.send(`Your username is ${request.body.username}
        and your password is ${request.body.password}.`);
});

Now, when we fill out our form and click submit, we can access the username and password by using request.body.username and request.body.password respectively. The output will be the following if we type in WittCode for the username and mypassword for the password.

Image

What is request.body?

The body attribute of the request object contains key-value pairs of data submitted in the request body. It is undefined by default but is populated by the body-parsing middleware express.json() and express.urlencoded().

Name Attribute

The reason we can access the entered username and password with request.body.username and request.body.password is because of the name attribute in our pug form.

input(type='text' name='username')
input(type='text' name='password')

The name attribute is used to reference the form data after it has been submitted.

Summary

But there we have it! In the next video we will be going over connecting our Express application to a database. If this article was helpful, please consider donating using the link at the top of the page, sharing this article, and subscribing to my YouTube channel WittCode!