Create Dependent Dropdown Lists with Fetch

Last updated: August 29, 2026.

Dependent dropdowns are useful for country and state, category and product, or customer and project. Send a stable identifier to the server and build options with textContent.

Load options for the current selection

const parent = document.querySelector('#country');
const child = document.querySelector('#state');
let controller;

parent.addEventListener('change', async () => {
  controller?.abort(); controller = new AbortController();
  child.replaceChildren(new Option('Loading...', '')); child.disabled = true;
  try {
    const response = await fetch('/api/states?country=' + encodeURIComponent(parent.value), { signal: controller.signal });
    if (!response.ok) throw new Error('Request failed');
    const rows = await response.json();
    child.replaceChildren(new Option('Choose a state', ''));
    for (const row of rows) child.add(new Option(row.name, row.id));
    child.disabled = false;
  } catch (error) { if (error.name !== 'AbortError') child.replaceChildren(new Option('Could not load options', '')); }
});

Secure the API too

  • Authorize the endpoint on the server.
  • Validate the parent identifier.
  • Return only the fields the list needs.
  • Handle empty results and network failure.

Building database forms with dependent fields?
PHPRunner can generate linked dropdowns and data-driven web forms. Explore PHPRunner.

Keep selection changes race-safe

When the parent changes quickly, cancel the previous request so an older response cannot overwrite newer options. Disable the child while loading and make empty or failed results understandable.

Test rapid changes, a blank parent, no matching rows, network failure, and a previously saved child value. The API must validate and authorize the parent identifier independently.

  • Build option text with the DOM.
  • Return only required fields.
  • Cache stable lists when useful.

Progressive enhancement matters: preserve semantic HTML and a usable server-side path. Test keyboard operation, failure states, and rapid repeated actions rather than only the ideal mouse interaction.

Continue with debounced input and Access form parameters.

Reference: MDN Fetch API guide.

admin

admin