JavaScript Forms
The tea counter keeps one slip. The form is #slip. It has a text field #guest whose name is also guest, a number field #cups whose name is also cups, and a button #send with type="submit". Under the form, #note says blank.
A form collects named fields. You read what the visitor typed from each field’s value. That property is always a string, even when the input’s type is number. Sending the form is a submit event on the form, not a click you handle on each field. If you do not call preventDefault, the browser loads the form’s address and this page is gone. This slip calls preventDefault, so the note can still be read. The page sets guest to lida, sets cups to 2, clicks send once, and the line reads lida / 2 / stayed.
Not the ticket strip
The ticket strip put one click listener on a parent and read event.target. Its line was red / blue / gold / 1. That page did not call preventDefault. The plaque page did call it, on a link, and the line was click / seal / plaque / true / quiet. This slip is neither. There is no gold button and no currentTarget. The event name is submit. The values you care about are lida and the string 2.
getElementById("guest") finds the field by id. slip.elements.guest finds it by the name attribute, through the form. This markup sets id and name to the same word so both roads work. A later lesson checks whether a field is empty or well formed. This page does not. An empty guest would still send.
What the slip records
The note starts as blank. Guest and cups start empty. The button label stays send. Read the rows in order. Each snippet starts from that empty slip, except the page row, which is the demo at the bottom. The page demo clicks send once.
📊 What the slip records
| Moment | What you read | Note text | Easy to mix up |
|---|---|---|---|
| guest set to lida | guest.value |
lida | reading the id guest |
| cups set to 2 | cups.value |
2, and it is a string | expecting the number 2 |
| click send, handler writes stayed | the note | stayed | calling slip.submit(), which skips the listener |
| both names, through the form | elements.guest and elements.cups |
lida 2 | reading elements.slip |
| page script | the line | lida / 2 / stayed | red / blue / gold / 1 |
value does not convert a number input into a number. cups.value after you store 2 is the characters 2. typeof cups.value is "string". If you need a number later, you convert on purpose. This line does not. It shows the string the field actually holds.
send.click() fires submit on the form, because the button’s type is submit. slip.submit() is a different call. It tells the browser to send the form and does not run your submit listener, so preventDefault inside that listener never gets a chance. This page uses the button click.
Two roads to the same field
getElementById("cups") uses the id. slip.elements.cups uses the name, and only after you already hold the form. This markup sets both attributes to the same word, so the two roads agree. If the name were count and the id stayed cups, elements.cups would be missing and elements.count would be the field.
The guest’s name
The field starts empty. The script stores lida in value, then reads that same property back into the note. Nothing is sent yet.
let guest = document.getElementById("guest");
let note = document.getElementById("note");
guest.value = "lida";
note.textContent = guest.value;
console.log(note.textContent);
The log is lida. The id is guest. The note is not the word guest. It is whatever string sits in value.
How many cups
Fresh slip. The cups field is type="number". Store 2 and read value, then ask typeof.
let cups = document.getElementById("cups");
let note = document.getElementById("note");
cups.value = "2";
note.textContent = cups.value + " " + typeof cups.value;
console.log(note.textContent);
The log is 2 string. The field showed a number box, and the script still received text. Store the number 2 without quotes and the property still comes back as the string "2".
The send button
Fresh slip again. The listener is on the form, for submit. It calls preventDefault and writes stayed. Then the page clicks the send button. It does not call slip.submit().
let slip = document.getElementById("slip");
let note = document.getElementById("note");
function pour(event) {
event.preventDefault();
note.textContent = "stayed";
}
slip.addEventListener("submit", pour);
document.getElementById("send").click();
console.log(note.textContent);
The log is stayed. The listener ran, so the browser did not leave this page. Call slip.submit() instead of clicking send and the function pour does not run. The note would stay blank.
Names on the slip
Fresh slip. No listener this time. The script writes both fields through slip.elements, using the name attributes, then joins them in the note.
let slip = document.getElementById("slip");
let note = document.getElementById("note");
slip.elements.guest.value = "lida";
slip.elements.cups.value = "2";
note.textContent = slip.elements.guest.value + " " + slip.elements.cups.value;
console.log(note.textContent);
The log is lida 2. elements.guest is the input whose name is guest, not an element whose id is slip. The space is only a separator in the note. The page line later uses / instead.
The line under the slip
The script sits at the end of the body, after the form and the paragraphs exist. mark starts as left. The listener prevents the default send, copies the two values into the note, and sets mark to stayed. Then the script fills lida and 2 and clicks send once. The line is written after that click.
<!DOCTYPE html>
<html>
<head>
<title>forms — page</title>
</head>
<body>
<form id="slip">
<input id="guest" name="guest" type="text">
<input id="cups" name="cups" type="number">
<button id="send" type="submit">send</button>
</form>
<p id="note">blank</p>
<p id="line">…</p>
<script>
let slip = document.getElementById("slip");
let note = document.getElementById("note");
let mark = "left";
function pour(event) {
event.preventDefault();
note.textContent =
slip.elements.guest.value + " / " + slip.elements.cups.value;
mark = "stayed";
}
slip.addEventListener("submit", pour);
slip.elements.guest.value = "lida";
slip.elements.cups.value = "2";
document.getElementById("send").click();
document.getElementById("line").textContent =
note.textContent + " / " + mark;
</script>
</body>
</html>
The line reads lida / 2 / stayed. The first token is the guest. The second is the cups field as text. The last token is mark, and the listener ran, so that token is stayed, not left. The note ends as lida / 2. The word blank is gone. The ticket line is another page. This slip does not check that the fields are filled in.
At the counter
- Store lida in the guest field and read
value. The note is lida. - Store 2 in cups and read
valuewithtypeof. The note is 2 string. - Listen for submit, call
preventDefault, and click send. The note is stayed. - Read both fields through
slip.elements. Then read the page line: lida / 2 / stayed.
Misses at the counter
The labels stay guest, cups, and send. The note is not the word slip.
- Treating
cups.valueas the number 2 - Calling
slip.submit()and waiting forpourto run - Forgetting
preventDefault, so the browser loads the form’s address - Reading the id guest when you wanted
value - Looking up
slip.elements.slip - Checking empty fields or patterns on this page
- Reading the line as red / blue / gold / 1
Keep this
guest.valueis lida after you store lidacups.valueis the string 2, andtypeofis"string"send.click()runs the submit listener;slip.submit()does notpreventDefaultis why the page is still here and the note can say stayedslip.elements.guestandslip.elements.cupsread the named fields- The page line reads lida / 2 / stayed
🧠 Test Your Knowledge
Test Your Knowledge
Challenge yourself with this interactive quiz and see how well you understand the topic
📝 Instructions
- Read each question carefully
- Select the best answer for each question
- You can retake the quiz as many times as you want
- Your progress will be shown at the top