When I was starting out and developing my first web application, my first impression of the structure of the web was very favorable. I appreciated the built-in and enforced separation of behavior from content (HTML) and styling (CSS).
I found front-end development frustrating. If I changed one little thing in the front end, I would have to remember to change it in the back end. The same was the case if I changed something in the back end. It was increasingly complex, increasingly difficult to remember what I had done before. Eventually, I found it so frustrating that I quit. I was only going to do back-end development from that point on.
I distinctly remember the first time I rendered an HTML form in my web application. I had defined a click handler for the button in the form, but when I clicked on it, the whole application disappeared, and frustrated with this seemingly horrifying behavior, I turned to Stack Overflow for the answer.
Pretty soon I was adding
event.preventDefault(); as the first line of every click handler that I ever wrote so that my application would not have any unexpected behavior.
How a form works
I did not understand what the default behavior of an HTML form was until I participated in our internal ROCA workshop. For some people this may seem completely obvious, but it was not for me, and in my experience, I am not the only one.
It turns out that HTML is not only meant as a markup language to describe how a page is structured. It also has semantics. The most common semantic element is a link:
Another very powerful semantic element in HTML is a form:
The default method for a form is the
GET method. This means that a form with only an action and a submit button is semantically identical to a link. However, a form also makes it possible to modify the query string for the url. The above form, if it were clicked, would send the following
GET request to the server:
Different input fields offer different semantics. A checkbox field
will generate the query string
?food=Cheese only if the checkbox is selected.
If you use radio buttons in a form, the browser ensures that at maximum one of the options is selected.
A select element performs a similar function, but displays the values in a drop-down menu.
When you want to send a list of elements to the server, you can just give multiple inputs the same name.
This will then be translated as the query string
?order=Hamburger&order=Cheese which will be interpreted by the server as a list of values.
Forms are, therefore, a way of specifying a request to the server. Once the form is submitted, the request is sent to the server and the server handles it.
Handling Requests on the Server
The second piece of the puzzle is handling the requests on the server. A form is simply a tool for constructing an HTTP request and sending it to the web server that is serving the web application. For this reason, to understand how a form works, it is important to understand the fundamentals of HTTP.
An HTTP request consists of a method (e.g.
GET) and a URI to a resource (e.g.
/cat.png). An HTTP server takes this request and decides what to do with it. Then it returns an HTTP response to the user which contains a status code and content. A web browser knows both how to send an HTTP request (via link or form) and how to handle the response that comes back from the server. The most common action will be to simply render the content of the response in the browser window. It is also possible to use URL redirection to navigate within the application.
By default, an HTML form only supports the
POST HTTP methods. According to the HTTP 1.1 Specification,
GET requests should only be used to retrieve resources, never to modify them. A
POST request, however, can be used to modify existing resources.
Other HTTP methods, like
PATCH can be very useful when creating RESTful services. Many web frameworks also provide for these HTTP methods by tunneling within a
Even with all of this information, it might be difficult to conceptualize how such a web application could be constructed.
As an example, consider a web application for managing ebooks. By executing
GET /books, you would get an HTML page listing all of the books that you have added so far. You can also render an HTML form in the page, allowing you to add a book with
POST /books?title=Title&author=Author&nrStars=4. After adding the book, the application might redirect you back to the
/books page where you would see the new book rendered. The page might contain links to a particular book,
GET /books/:bookid, which would display more information about the book, and you could render forms in the page to allow you to update the book (
PUT /books/:bookid) or remove it from your library (
Luckily for us, there are great web frameworks that are available to help us. Some of them include:
- Compojure in Clojure
- Rails in Ruby
- Spring Boot in Java
- Play in Scala and Java
- Phoenix in Elixir
- Express for Node.js
Why Availability Matters ↩