Let’s get better at forms #1: The form element and its children

Forms are an essential part of making the web accessible. Not only that, but they provide a lot of functionality out of the gate that we sometimes take for granted or even re-implement ourselves with brittle JavaScript solutions.

<form action="path/to/myFormHandler.php" method="post" id="myForm">
    ...
</form>

action

The url the backend will use to handle form data. This is required if the form is to function without the use of JavaScript.

method

Should be either "get" or "post". The default is "get" but I find it more predictable and explicit to always include the method attribute.

"get"

  • encodes form data into the url, and can be bookmarked
  • should be used for requests that have no side-effects, such as a search form
  • should NOT be used for any kind of sensitive data, such as passwords
  • is restricted by the safe url limit of browsers and web servers (generally, a good rule of thumb to be below 2048 characters)
  • is restricted to ascii characters to be url-safe
  • can be cached due to the lack of server-side effects

"post"

  • encoded form data into the request body, and cannot be bookmarked
  • should be used for forms that create/modify/delete data, such as signup and user profile editing
  • should be used (in conjunction with HTTPS) for submitting sensitive data to the server
  • supports file uploading and large parameter payloads

id

While the id attribute is not strictly required, I find it very useful to include on the base form element for a few reasons.

  • Using an ID exposes the form to the document’s list of forms via JavaScript, available at document.forms.myForm. This gives the developer a simple, clear, and efficient way to access any form on the page instead of having to resort to queries such as $('form.myFormClass')[0] or document.querySelector('form.myFormClass').
  • It allows you to deep link to a form, just like any other ID-labelled element.
  • HTML5 introduced a new form attribute on form controls that allows the form to include them even if they're not a descendant of the <form> element. While support is questionable now, its use in the future may reduce the number of styling hacks needed when creating form markup.

Children of the form

Controls within the form all share a few characteristics. When the form is submitted, controlls within the form send their current values to the server.

Initial value

Most form controls have an initial value set. If it's a binary input like a checkbox or radio button, the initial value is whether or not it's checked. Text inputs have an initial value specified in the value attribute.

Initial values come into play when a form is reset, either by the user interacting with a reset button or calling the reset() method on the form via JavaScript.

id vs name

These two similar attributes are often a cause of confusion. While they both label the control, they actually serve two different purposes.

Use an id attribute to identify a specific form control. Doing so will allow a <label> element to target the control with its for attribute. Another benefit of using an ID is that, similar to document.forms, a shortcut is provided in the DOM API to select form elements with IDs. We’ll go into more depth later. id attributes must be non-empty and unique within the page.

The name attribute serves a couple of purposes on controls. First, it is the key used when sending data to the server in key-value pairs. For example, searching for "R2D2" in a form where the search input has a name of "search" might end with this: ?search=R2D2. The second use is grouping elements such as radio buttons. Radio buttons with the same name will limit the number of checked buttons to 1 element in the set. name attributes CAN be duplicated within a form, and therefore, are not a fool-proof way to select an element.

Disabled states

Form controls, such as <input> elements, have a binary disabled attribute that has a few side effects. Disabled controls:

  • are often greyed out by the browser and user interaction is prohibited
  • are NOT sent to the server via form submission
  • do not validate via HTML5 form validation
  • can be styled with the :disabled css selector (IE9+) or the [disabled] css attribute selector (IE7+).

Controlling the form

There are a few key ways to manipulate a form via JavaScript. Here are the essentials.

form.submit()

Submitting a form via JavaScript will send data to the server. This mimics what would happen if the user clicked a submit button.

form.reset()

Reset will clear the form and reset each control to its initial value.

form.elements

Similar to document.forms, the DOM provides a collection on the form element itself called elements. Using this collection, we can grab a reference to any form control child with an ID by using form.element.myControlID.

Summary

Now that we’ve started from scratch with forms, we can look at more complex patterns within them. To recap what we’ve covered here:

  • Forms need action, method, and (preferrably) id attributes.
  • Use "get" and "post" correctly and responsibly.
  • Form elements have initial values that can be easily reset.
  • Disabled elements behave differently than normal controls.
  • Make use of document.forms and form.elements to simplify DOM selection and traversal.