Forms and JavaScript

This reading is about how we can use JavaScript to process the data that the user enters into a form. We'll look at the following topics:

  • submit handlers
  • preventing defaults
  • serializing forms
  • resetting forms
  • a generalized form-handler

Form Submission

Let's talk about forms. HTML forms were invented so that a page could collect information from the user and allow it to be packaged up and submitted to a server for some kind of processing. Think about forms on Amazon.com or Ebay.com or any other kind of web application. Think about the customer feedback questionnaires we are constantly being asked to fill out. Even Facebook posts. All of those are forms being submitted to servers.

We can write JavaScript code that gets triggered when a form is submitted.

Let's start with the following form

Go ahead and fill it out and submit it if you like.

Note that the URL changes when you submit this form, with your form data (key/value pairs) appearing in the URL. Here, there's only one input, name="ans", but in general we could have many inputs. We saw quite a few inputs in our pizza form; submit that form and look at the URL.

Submit Handlers

The first thing we want to do is add a JS function that will be invoked when the form is submitted. Form submission is a kind of event, so this is a kind of event handler.

What should our function do? For now, let's just alert the user that they submitted the form. A little bit of jQuery will suffice.

There are two equivalent ways of attaching a function to the form-submission event:

$("#form2").submit(function () { alert("form submitted!"); });

and

$("#form2").on('submit', function () { alert("form submitted!"); });

The former is slightly more succinct. Later, we will learn a small advantage of the second form. For now, you may use either one.

Preventing Defaults

Usually, we want to send the data to a server when a form's submit button is clicked (or the user presses enter in a text field), but in this case we don't. We want to prevent the default behavior, so we'll change our event handler to get the event object and use the preventDefault() method. We saw this back in OtterGram when we wanted to prevent the default behavior of clicking on a hyperlink. This is exactly the same idea.

Here's the JS/JQ code. Notice that we added an argument to the event handler function, to gain access to the event object that the browser will supply.

$("#form3").submit(function (evt) {
    evt.preventDefault();
    alert("form submitted!");
});

Go ahead and submit this form. Note that the URL doesn't change with this event handler. Of course, that's because we've prevented the default behavior, so we are still on the same page.

jQuery and its pitfall

What's wrong with the following combination of HTML and CSS and JavaScript?

<form id="form3"> ...</form>
#from3 { border: 1px solid green; }
$("#from3").submit(function (evt) {
    evt.preventDefault();
    alert("form submitted!");
});

Right; spelling. In CSS, you won't get an error message; it's just a rule that doesn't happen to apply to anything. Similarly, in jQuery, it'll look up everything that matches that selector, and add the given function as a submit handler. Alas, nothing matches that selector, but jQuery doesn't give you an error message. It treats it as an empty set: valid but useless.

Recall that this is why I implemented the bounds plug-in to jQuery. So, using my plug-in, we can do:

$("#from3").one().submit(function (evt) {
    evt.preventDefault();
    alert("form submitted!");
});

Now, the code would produce an error message, and we can debug it.

Values

If we are going to process the form on the client (in the browser), rather than on the server, we need a way to get out the values of the inputs.

jQuery provides a useful .val() method that either reads the current value or sets it. We will usually be interested in reading the value.

Let's start with a more interesting form, returning to our pizza form:

Recall that this form had the following inputs:

  • name="customer"
  • name="phone"
  • name="addr"
  • name="size"
  • name="due"
  • name="instructions"

Since name is an attribute of the input, we can use the attribute selector syntax (square brackets around the attribute=value expression) to select those inputs. For example, [name="customer"] will select the input that holds the customer's name. Then, we can use the .val method to get the user's input.

Try it! Fill out the form and copy/paste the following expression into the JS console:

[ $('[name="customer"]').val(),
$('[name="phone"]').val(),
$('[name="addr"]').val(),
$('[name="size"]').val(),
$('[name="due"]').val(),
$('[name="instructions"]').val() ];

Exercise: find a JS expression that will return a dictionary of all the form data.

Values of Radio Buttons

The above works very well, even on things like select. but it doesn't work for radio buttons because all the radio buttons in a group share the same name. However, the selector language includes a "pseudo-class" called :checked that selects the checked radio button in a group. Try it here:

You can try the following expression in the JS console:

$("[name=station]:checked").val();

Summary

  • Forms collect data from the user as a set of name/value pairs
  • JavaScript can access that data, pulling it into variables that we can use in ordinary programming
  • You can get the value using jQuery: $("[name=customer]").val()
  • For radio buttons you can use the :checked pseudo-class: $("[name=station]:checked").val()
  • We can attach a function as an event handler for form submission using $(selector).submit(fun); or $(selector).on('submit', fun);
  • The event handler can use event.preventDefault() to prevent the form being submitted to the server.