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.