Form properties & elements
Access forms and form controls with document.forms, form.elements, input values, checkboxes, radios, selects, and options.
- 01Find controls safelyUse
document.forms,form.elements,fieldset.elements, andelement.formwithout name collisions. - 02Read real valuesChoose between
.value,.valueAsNumber,.valueAsDate,.checked, and radio-list.value. - 03Handle choicesRead and change checkboxes, radio groups, selects, options, and multiple selections.
Forms as clipboards
Forms are where page data becomes user data. A login box, checkout page, search panel, survey, settings screen, or newsletter signup is a collection of controls: text inputs, checkboxes, radio buttons, menus, textareas, buttons, and sometimes grouped fieldsets. JavaScript does not need to guess where those controls are. Every form exposes a built-in index.
The central idea is: get the form, use form.elements to find controls, then read the property that matches each control. Text-like controls use value. Checkboxes use checked. Radio groups have one shared value. Selects have value, selectedIndex, options, and selectedOptions.
Imagine a clipboard at a front desk. The sheet has labeled blanks, and the receptionist uses an index to jump to “Email” or “Plan.” form.elements is that index for the browser.
- In real life: The whole clipboard
- In JavaScript: The
formelement - In real life: A labeled field, like Email
- In JavaScript: A named control, like
name="email" - In real life: The clipboard's index
- In JavaScript:
form.elements - In real life: Looking up the Email row
- In JavaScript:
form.elements.emailorform.elements.namedItem("email")
Where the analogy stops: A paper clipboard cannot have a field named submit that hides a built-in method, and it cannot turn one label into a radio group. Real forms can, so prefer form.elements.name over form.name.
This lesson follows Attributes & properties and links back to Type conversion when strings pretend to be numbers. The next lesson, Form events, will react to changes and submissions; this one focuses on reading the controls accurately.
form.elements
INTERACTIVEStart with the form. document.forms is a collection of forms in the document. You can read by index, such as document.forms[0], or by a form name, such as document.forms.signup. Once you have the form, form.elements gives the controls that belong to that form.
form.elements is an HTMLFormControlsCollection. It includes button, fieldset, input, object, output, select, and textarea. It does not include <input type="image">. A disabled control still appears in the collection; it is excluded later when the browser builds submitted form data.
Named access like form.email works in browsers, but a field named submit can shadow form.submit, and a field named action can shadow form.action. form.elements.email says “look in the controls” and avoids that trap.
const form = document.forms.signup;const email = form.elements.email;const age = form.elements.age;const plan = form.elements.plan;const snacks = form.elements.snacks; email.value; // always a stringage.valueAsNumber; // number, or NaN when emptyplan.value; // checked radio value, or ""snacks.selectedOptions;- form.elements.length
0- form.elements.email.value
""- password length
0- age.value / valueAsNumber
"" /- birthday.valueAsDate
- textarea.value
""- checkboxes
terms false, newsletter false- form.elements.plan.value
""- select value / index
/ -1- selectedOptions
- multiple selected
- disabled field value
- fieldset.elements / element.form
0 / false
Change any field. The panel reads the real form through DOM APIs.
Notice the back-reference too: a control’s element.form points to the form it belongs to. A fieldset also has its own fieldset.elements, a smaller index for the controls inside that group.
Input values
STEP THROUGHThe most important value rule is simple but surprising: input.value is always a string. A number input that visually contains 4 has input.value === "4". If you add 1 to that string, JavaScript concatenates and gives "41".
function readNumberInput(rawValue) { const value = String(rawValue); const plusOne = value + 1; const valueAsNumber = value === "" ? NaN : Number(value); const fixed = valueAsNumber + 1; return { value, plusOne, valueAsNumber, fixed };} const result = readNumberInput("4");console.log(result.plusOne);console.log(result.fixed);Predict whether the input behaves like text or a number, then step through the recorded run.
script
function readNumberInput(rawValue) { const value = String(rawValue); const plusOne = value + 1; const valueAsNumber = value === "" ? NaN : Number(value); const fixed = valueAsNumber + 1; return { value, plusOne, valueAsNumber, fixed };} console.log(result.plusOne);console.log(result.fixed);NaN.Use valueAsNumber when the control has a numeric interpretation, such as type="number" or type="range". Empty number inputs read as "" through value and NaN through valueAsNumber. Use Number.isNaN before doing math.
Date-like inputs have valueAsDate where supported. The string value might be "2026-09-25", while valueAsDate is a Date object, or null when the field is empty. A disabled control can still be read from form.elements, but it will be skipped by submission; a readonly control is included in submission.
Checkboxes & radios
INTERACTIVEA radio group answers “choose one.” A checkbox answers “is this switch on?” Read radio groups through the group value; read checkboxes through checked.
- In real life: Old car radio preset buttons
- In JavaScript: Radio inputs sharing one
name - In real life: Pressing one preset pops the others out
- In JavaScript: Only one same-name radio can be checked
- In real life: Independent light switches
- In JavaScript: Separate checkboxes with separate
checkedbooleans
Where the analogy stops: Radio exclusivity depends on the same form and same name. Checkboxes can share a name for submission, but they still do not become exclusive.
Radio buttons with the same name form one group. In form.elements, that name returns a RadioNodeList. Its value is the checked radio’s value, or "" if none is checked. Checkboxes are independent; checkbox.checked is a boolean.
const newsletter = document.querySelector("#newsletter");const pro = document.querySelector("#plan-pro");const selectAll = document.querySelector("#select-all"); newsletter.checked = true; // no input/change event firespro.checked = true; // same name: other radio pops outselectAll.indeterminate = true; // visual mixed stateselectAll.checked = false;- newsletter.checked
false- radio group value
"free"- free / pro checked
true / false- select-all checked / indeterminate
false / false- change events observed
0
Click the buttons. Programmatic property writes change state but do not increment the event counter.
Setting checked or value from JavaScript does not fire input or change by itself. That is useful: scripts can repair state without accidentally pretending the user acted. If you want listeners to run, dispatch an event intentionally. A “select all” checkbox can use indeterminate to show a mixed visual state while some child checkboxes are selected.
select & option
INTERACTIVEFor a select, value is the chosen option’s code, selectedIndex is the option’s position, and options is the menu. Multiple selection changes the question from “which one?” to “which options?”
- In real life: The whole menu
- In JavaScript:
select.options - In real life: Snack code B7
- In JavaScript:
select.value - In real life: Snack position in the menu
- In JavaScript:
select.selectedIndex - In real life: A buffet plate
- In JavaScript: A
multipleselect andselectedOptions
Where the analogy stops: A vending machine gives one snack at a time, but a multiple select can hold several selected options. Also, option values are still strings.
const select = document.querySelector("select"); const tea = new Option("Tea", "tea", false, false);select.add(tea);select.value = "tea"; select.multiple = true;select.options[0].selected = true;const chosen = [...select.selectedOptions].map((option) => option.value);tea.remove();- select.value
""- selectedIndex
-1- select.multiple
false- selectedOptions
Add Tea with new Option, switch to multiple mode, then remove the selected option.
Create options with new Option(text, value, defaultSelected, selected). Add them with select.add(option). Remove them with option.remove(). For multiple selects, selectedOptions is an HTMLCollection, so convert it before mapping: [...select.selectedOptions].map(option => option.value).
input.valuecheckbox.checkednumberInput.valueAsNumberform.elementsform.elements.planselect.selectedOptionsselect.selectedIndexform.elements.plan.value
Sort each form API by the kind of value it gives you.
Where you will use this
PRACTICALIn real interfaces, you often read a form before validating, previewing, enabling a button, saving a draft, or building a request. The function below is deliberately boring: that is what good form-reading code should be. Each line chooses the property that matches the control.
function readSignup(form) { const elements = form.elements; return { email: elements.email.value.trim(), age: elements.age.valueAsNumber, plan: elements.plan.value, interests: [...elements.interests.selectedOptions].map((option) => option.value), acceptsTerms: elements.terms.checked, };}| Question | Use | Why |
|---|---|---|
| What text is in the field now? | input.value | The live value is always a string. |
| What number did the user enter? | input.valueAsNumber | It gives a number or NaN; check before math. |
| Is the box on? | checkbox.checked | The on/off state is boolean. |
| Which radio in this group is checked? | form.elements.plan.value | The RadioNodeList summarizes the group. |
| Which menu item is selected? | select.value and selectedIndex | One gives the option code; the other gives position. |
| Which multiple options are selected? | [...select.selectedOptions] | The result is a collection of option elements. |
Common misconceptions
WATCH OUT- “A number input gives a number.” Its
valueis a string. UsevalueAsNumberor convert explicitly. - “
form.emailis always safe.” It can collide with built-in form properties. Preferform.elements.email. - “Disabled controls are not in
form.elements.” They are in the collection; they are excluded from submission. - “A radio button is just a checkbox with a round shape.” Same-name radios form an exclusive group and can be read as a
RadioNodeList. - “Changing
checkedfrom code fireschange.” Programmatic property writes do not fire form events by themselves. - “
selectedOptionsis an array.” It is anHTMLCollection. Spread it into an array before using array methods.
Practice exercises
5 EXERCISESPredict the boolean printed by line 4.
const value = "";
const valueAsNumber = value === "" ? NaN : Number(value);
console.log(value);
console.log(Number.isNaN(valueAsNumber));const value = "";
const valueAsNumber = value === "" ? NaN : Number(value);
console.log(value);
console.log(Number.isNaN(valueAsNumber));The model prints an empty first line, then true because Number.isNaN(valueAsNumber) detects the empty numeric view.
What value would form.elements.plan.value give when the Pro radio is checked?
const plan = { value: "pro" };
console.log(plan.value);const plan = { value: "pro" };
console.log(plan.value);A RadioNodeList exposes the checked radio's value through .value, so the answer is pro.
Predict the printed string for a multiple select with Tea and Cake selected.
const selectedOptions = [{ value: "tea" }, { value: "cake" }];
console.log(selectedOptions.map((option) => option.value).join(","));const selectedOptions = [{ value: "tea" }, { value: "cake" }];
console.log(selectedOptions.map((option) => option.value).join(","));The selected option values are mapped and joined, producing tea,cake.
What does the first console.log print?
const events = [];
const checkbox = { checked: false };
checkbox.checked = true;
console.log(events.length);
events.push("change");
console.log(events.length);const events = [];
const checkbox = { checked: false };
checkbox.checked = true;
console.log(events.length);
events.push("change");
console.log(events.length);After checkbox.checked = true, no event has fired, so the first count is 0. The later manual push makes the second count 1.
Write a function that reads a profile form with email, age, radio group plan, multiple select interests, and checkbox terms.
function readProfile(form) {
// return email, age, plan, topics, and subscribed
}function readSignup(form) {
const elements = form.elements;
return {
email: elements.email.value.trim(),
age: elements.age.valueAsNumber,
plan: elements.plan.value,
interests: [...elements.interests.selectedOptions].map((option) => option.value),
acceptsTerms: elements.terms.checked,
};
}The solution reads each control through the form collection and picks the property that matches its type.
Quiz
7 QUESTIONSQuestion 1 of 7Why is
form.elements.emailusually better thanform.email?Choose an answer to see the explanation.
Question 2 of 7What does this print?
Read the code, then predictconst value = "4"; console.log(value + 1); console.log(Number(value) + 1);Choose an answer to see the explanation.
Question 3 of 7A form has three radios with
name="plan"and none is checked. What isform.elements.plan.value?Choose an answer to see the explanation.
Question 4 of 7Which statement about checkboxes is true?
Choose an answer to see the explanation.
Question 5 of 7What does this program print?
Read the code, then predictconst events = []; const box = { checked: false }; box.checked = true; console.log(events.length);Choose an answer to see the explanation.
Question 6 of 7For a single-select menu, what does
selectedIndexmean?Choose an answer to see the explanation.
Question 7 of 7Which constructor call creates and selects a new option?
Choose an answer to see the explanation.
Key takeaways
document.formsfinds forms;form.elementsfinds the controls belonging to one form.- Prefer
form.elements.nameoverform.namebecause control names can collide with form properties. input.valueis a string. UsevalueAsNumber,valueAsDate, or explicit conversion when you need another type.- Checkboxes use
checked; same-name radio groups expose aRadioNodeList.value. - Selects expose
value,selectedIndex,options, andselectedOptions; create choices withnew Option.
Final definition: form element APIs are the DOM properties and collections that let JavaScript find controls and read their current values accurately.
Up next: Form events.