Skip to content
academia.sh

Lesson 21 / 25

Input Types

The distinction between text, number, date, choice, and file fields; how much type information survives submission, and the shape values take when they reach the server.

Contents

The previous lesson built a form with a single kind of field. But the data to be collected is not always free text: a number, a date, a time, a single choice, a multiple choice, long text, a file. The input element’s type attribute makes this distinction.

Choosing a type affects three things at once: the interface the user sees, the validation the browser applies, and the shape the value takes on submission. This lesson focuses on the third, because the first two are only understood correctly once the third is known.

Three Effects of a Type

Once a type is declared, the browser offers a matching interface: increment buttons on a number field, a calendar on a date field, a picker on a color field. These interfaces vary by browser and device; on narrow screens, the type declaration also determines the keyboard layout — digit keys for a number, a layout including the @ character for email.

A type also brings a constraint: submission is blocked when an invalid value is entered. This behavior is the subject of the next two lessons.

The third effect is the submission format, and it is defined.

How Values Reach the Server

// input-values.mjs — the values different types produce and how they look on the server
import { createServer } from "node:http";

// An unchecked checkbox and a disabled field never enter the entry list at all.
const entryList = [
  ["name", "North Slope"],           // type="text"
  ["temperature", "-4.2"],           // type="number"
  ["measurementDate", "2024-03-12"], // type="date"
  ["measurementTime", "07:30"],      // type="time"
  ["threshold", "18"],               // type="range"
  ["verified", "on"],                // checked type="checkbox", value not written
  ["source", "automatic"],           // selected type="radio"
  ["tag", "humidity"],               // <select> selected option
  ["tag", "wind"],                   // <select multiple> second selected option
  ["note", "first line\r\nsecond line"], // <textarea>: line endings become CRLF
];

const server = createServer((request, response) => {
  const chunks = [];
  request.on("data", (chunk) => chunks.push(chunk));
  request.on("end", () => {
    const body = Buffer.concat(chunks).toString();
    console.log("raw body:");
    console.log(body);
    console.log("--- decoded pairs on the server ---");
    for (const [key, val] of new URLSearchParams(body)) {
      console.log(key.padEnd(16), JSON.stringify(val), "(" + typeof val + ")");
    }
    response.writeHead(204).end();
  });
});

server.listen(0, "127.0.0.1", async () => {
  await fetch("http://127.0.0.1:" + server.address().port + "/record", {
    method: "POST",
    headers: { "content-type": "application/x-www-form-urlencoded" },
    body: new URLSearchParams(entryList).toString(),
  });
  server.close();
});
raw body:
name=North+Slope&temperature=-4.2&measurementDate=2024-03-12&measurementTime=07%3A30&threshold=18&verified=on&source=automatic&tag=humidity&tag=wind&note=first+line%0D%0Asecond+line
--- decoded pairs on the server ---
name             "North Slope" (string)
temperature      "-4.2" (string)
measurementDate  "2024-03-12" (string)
measurementTime  "07:30" (string)
threshold        "18" (string)
verified         "on" (string)
source           "automatic" (string)
tag              "humidity" (string)
tag              "wind" (string)
note             "first line\r\nsecond line" (string)

The last column of the output is the lesson’s most important result: every value is a string. Type information is not carried in submission. The server does not know that the temperature field is a number field; it receives the string "-4.2", and converting it to a number is its own job.

A direct consequence of this is that a type declaration is not a server guarantee. The topic is detailed in the fourth lesson.

Three more details are visible.

The date and time format is defined. Even though the interface the user sees uses a local format, the value sent has the shape YYYY-MM-DD and HH:MM. The server can parse the value without knowing which country the user is in.

The same name can appear more than once. The tag field was sent twice — the two selected options of a multiple-selection list. On the server side, this field needs to be read as a list; parsing that only takes the first value silently loses data.

Line endings in a long-text field become CRLF. %0D%0A appears in the body. Whatever operating system the user is on, the value sent is the same.

The Set of Types

Type Data collected Value sent
text single-line text the text entered
search search term the text entered
email email address the text entered
url url the text entered
tel phone number the text entered, format not checked
password masked text the text entered, unencrypted
number number period as the decimal separator
range number from a range number; the field does not display the value
date, time, month, week date and time in a defined format
checkbox yes/no or multiple choice value or on; nothing at all if unchecked
radio single choice from a group the value of the selected one
file file requires a separate encoding
hidden invisible carried value the value

The password type only masks the value on screen. The body goes out unencrypted; protection comes from the transport layer described in the Role of HTTPS lesson.

The range type does not show the selected value to the user, and is unsuitable when a value needs to be entered precisely; it suits an imprecise setting.

The hidden type is not a privacy mechanism: its value is visible in the source text and can be changed. It exists only to carry a piece of information back from the server.

Separate Elements

Three input types are not written with the input element.

textarea is multi-line text. Its initial value is given not through a value attribute but through the element’s content.

select is a choice from a list; option elements carry the choices, and optgroup carries groups of choices. The multiple attribute allows a multiple choice, and produces the repeated name seen in the output above.

<p><label for="tag">Tags</label>
   <select id="tag" name="tag" multiple size="4">
     <optgroup label="Atmosphere">
       <option value="humidity" selected>Relative humidity</option>
       <option value="wind" selected>Wind</option>
     </optgroup>
     <optgroup label="Surface">
       <option value="soil">Soil temperature</option>
     </optgroup>
   </select></p>

<p><label for="note">Description</label>
   <textarea id="note" name="note" rows="4">first line
second line</textarea></p>

If an option’s value attribute is not written, the value sent is the option’s text. value is written so that the sent value does not change when the visible text changes.

The output element carries the result of a computation and takes no part in submission; the behavior layer is what does the computing.

Suggestion List

A field may need to accept free text while also suggesting ready-made options. The datalist element combines these two behaviors: it carries options without restricting the field to them.

<p><label for="sensor">Sensor code</label>
   <input id="sensor" name="sensor" type="text" list="sensor-list">
   <datalist id="sensor-list">
     <option value="HUM-01">
     <option value="TMP-02">
     <option value="WND-03">
   </datalist></p>

The field’s list attribute names the list’s id. The user can pick a value from the list or type their own; the value sent is the field’s text either way. This is the distinction from select: select restricts the choices, datalist only suggests them.

Whether the list appears and how it is presented depends on the browser. For this reason, datalist content is written as a convenience, not a constraint; a field that genuinely needs to be restricted uses select or a validation rule instead.

In the Station Document

<fieldset>
  <legend>Measurement information</legend>
  <p><label for="date">Measurement date</label>
     <input id="date" name="date" type="date"></p>
  <p><label for="time">Measurement time</label>
     <input id="time" name="time" type="time" step="600"></p>
  <p><label for="value">Measured value (°C)</label>
     <input id="value" name="value" type="number" step="0.1"></p>
  <input type="hidden" name="station" value="north-slope">
</fieldset>

The step="600" value on the time field is the markup equivalent of a ten-minute measurement interval: six hundred in seconds. The hidden field carries the station code, and the user does not need to enter it.

Summary

  • The choice of type affects the interface, the validation, and the submission format together.
  • Every value sent is a string; type information is not carried to the server, and converting it is the server’s job.
  • Date and time values are sent in a defined format; the local format the user sees is not reflected in submission.
  • An unchecked checkbox is never sent at all; a multiple choice produces the same name more than once.
  • The password and hidden types provide no privacy: the first only masks on screen, the second is visible in the source text.

Next Step

The fields are declared, but what each one wants is understood only from the text next to it. Until that text is declared as bound to the field in the document, the field is nameless: clicking the label with a mouse does not move focus to the field, and a screen reader announces the field as “editable text.” The next lesson builds that bond, and makes the cases where the bond is missing visible with an audit.

To keep your progress and take notes, Log in

My notes

Log in to take notes.

Start typing to search.

↑↓ Esc navigate · open · close