HOWTO · JavaScript
Handle a Select Change Event in JavaScript
Use the change event to read a select element's value, handle multiple selects, and distinguish user changes from programmatic updates.
On this page
To run JavaScript when a user chooses a different option, listen for the change event on the <select> element. Read the selected value from event.target.value, then update the page or start the next operation. In JavaScript, the event name is change; onchange is the corresponding HTML attribute or event-handler property.
Listen for a single-select change
Give the control a label and a stable id, then attach a listener after the element exists in the document. The listener receives an Event, and event.target is the select whose value changed.
<label for="color">Choose a color:</label>
<select id="color" name="color">
<option value="">Choose one</option>
<option value="red">Red</option>
<option value="blue">Blue</option>
</select>
<p id="message" aria-live="polite"></p>
const color = document.querySelector("#color");
const message = document.querySelector("#message");
color.addEventListener("change", (event) => {
const value = event.target.value;
message.textContent = value ? `You chose ${value}.` : "Choose a color.";
});
If the user chooses blue, the paragraph becomes You chose blue.. The option’s value is the data value; if an option has no value attribute, its text is used as the value. Keep the label associated with the control so keyboard and assistive-technology users can identify it.
Read the selected option directly
For a single-select control, select.value returns the first selected option’s value. select.selectedIndex identifies its position, while select.options[select.selectedIndex] gives access to the option element and its label. A placeholder with value="" lets you detect that the user has not chosen a real value:
color.addEventListener("change", (event) => {
const select = event.target;
const option = select.options[select.selectedIndex];
message.textContent = select.value
? `You chose ${option.textContent}.`
: "Choose a color.";
});
Do not use visible text as an identifier when the application needs a stable value. An option may display United States while its submitted value is us.
Handle multiple select elements
One handler can serve several controls when they share a class or parent container. Event delegation is useful when controls are added later:
<label>Color <select class="filter"><option value="red">Red</option><option value="blue">Blue</option></select></label>
<label>Size <select class="filter"><option value="small">Small</option><option value="large">Large</option></select></label>
<p id="filters" aria-live="polite"></p>
const filters = document.querySelector("#filters");
document.addEventListener("change", (event) => {
if (!event.target.matches("select.filter")) return;
filters.textContent = `${event.target.name || "Filter"}: ${event.target.value}`;
});
For a multi-select control, add multiple and inspect selectedOptions rather than only value:
const values = [...select.selectedOptions].map((option) => option.value);
value represents the first selected option, so it is not enough when several choices are allowed.
change versus input and programmatic updates
For a <select>, change is the normal event for a committed user selection. It differs from text-entry behavior, where change may wait until the control loses focus. Use input only when your interaction needs that event; do not assume that both events have identical timing.
Changing select.value in JavaScript changes the control but does not automatically dispatch a user change event. Call the same update function directly, or dispatch an event when another listener must be notified:
select.value = "blue";
select.dispatchEvent(new Event("change", { bubbles: true }));
Dispatching an event does not simulate a real user action or submit a form. Validate the value and keep server-side validation for untrusted data. Use addEventListener("change", ...) for new code; inline onchange="..." handlers work, but mix markup and behavior and are harder to reuse.
Keep the event handler focused on the new selection. If changing one control
requires loading data, show a loading state and handle a failed request rather
than assuming that every value has a result. If the control is inside a form,
the name attribute determines the key submitted with the selected value;
the JavaScript listener does not replace normal form submission or validation.
For a server-backed filter, encode the value with the request API instead of
concatenating untrusted text into a URL or HTML string. These boundaries keep a
small selection handler predictable as the page grows.