jQuery / Selector / :selected — Seleccionar las opciones elegidas de un select

jQuery :selected coincide con los option elegidos actualmente dentro de un select. $("#fruit option:selected") obtiene elementos; $("#fruit").val() lee el valor directamente. El atributo HTML selected y el estado cambiado por el usuario pueden diferir.

Elementos, valores y etiquetas

La referencia :selected se aplica a opciones, no a casillas o radios. Limite la búsqueda al select o formulario correspondiente para no mezclar otros controles.

.text() es la etiqueta y .val() el valor. Sobre varios option, .val() devuelve solo el primero y .text() concatena textos. Lea todos los valores múltiples en el select; use map o iteración para información por elemento.

El ejemplo distingue una fruta y varios temas, usando JavaScript como etiqueta y js como identificador. Opciones y optgroup deshabilitados comparan selección con valores aptos para envío.

Ejemplo completo simple y múltiple

Guarde y abra selected-demo.html en UTF-8. Internet carga jQuery completo 4.0.0, sin servidor ni compilación. Windows Edge con 4.0.0 y 3.7.1 comprobó estado inicial, teclado, opciones deshabilitadas, selección vacía y Reset.

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Read selected options and submitted values</title>
  <script src="https://code.jquery.com/jquery-4.0.0.min.js"></script>
  <style>
    body { font: 16px/1.6 sans-serif; max-width: 740px; margin: 20px; }
    label { display: block; margin-top: 12px; }
    select, button { font: inherit; max-width: 100%; margin: 6px 0; }
    #topics { display: block; min-width: 230px; }
    pre { white-space: pre-wrap; overflow-wrap: anywhere; }
  </style>
</head>
<body>
  <form id="chooser">
    <label for="fruit">Fruit (single)</label>
    <select id="fruit" name="fruit"><option value="apple">Apple</option><option value="banana">Banana</option></select>
    <label for="topics">Topics (multiple)</label>
    <select id="topics" name="topics" multiple size="6">
      <option value="js" selected>JavaScript</option>
      <option value="css">CSS</option>
      <option value="html" selected disabled>HTML (disabled)</option>
      <optgroup label="Unavailable group" disabled><option value="legacy" selected>Legacy</option></optgroup>
    </select>
    <button type="button" id="set">Set Banana and CSS</button>
    <button type="button" id="clear">Clear topics</button>
    <button type="button" id="restore">Reset</button>
  </form>
  <pre id="result" aria-live="polite"></pre>
  <script>
    jQuery(function ($) {
      const $fruit = $("#fruit"), $topics = $("#topics"), form = document.querySelector("#chooser");
      let changes = 0;
      function values($options) { return $options.map(function () { return this.value; }).get(); }
      function render() {
        const $selected = $topics.find("option").filter(":selected");
        const data = new URLSearchParams(new FormData(form));
        $("#result").text("single=" + $fruit.val() + "\nsingleText=" + $fruit.find("option:selected").text() +
          "\nselectedOptions=" + JSON.stringify(values($selected)) + "\nvalues=" + JSON.stringify($topics.val()) +
          "\nselectedAttribute=" + JSON.stringify(values($topics.find("option[selected]"))) +
          "\nform=" + data.toString() + "\nchanges=" + changes);
      }
      $fruit.add($topics).on("change", function () { changes++; render(); });
      $("#set").on("click", function () {
        $fruit.val("banana").trigger("change"); $topics.val(["css"]).trigger("change");
      });
      $("#clear").on("click", function () { $topics.val([]).trigger("change"); });
      $("#restore").on("click", function () { form.reset(); changes = 0; render(); });
      render();
    });
  </script>
</body>
</html>

Fruit no tiene atributo selected, pero el primer Apple queda elegido. Hay tres temas seleccionados, aunque solo js puede enviarse.

single=apple
singleText=Apple
selectedOptions=["js","html","legacy"]
values=["js"]
selectedAttribute=["js","html","legacy"]
form=fruit=apple&topics=js
changes=0
  1. Banana actualiza single y singleText, también mediante change del teclado.
  2. Set Banana and CSS deja selectedOptions y values en ["css"], pero selectedAttribute sigue ["js","html","legacy"].
  3. Clear topics produce dos arrays vacíos; form solo conserva fruit.
  4. Reset restaura también HTML y Legacy deshabilitados.
  5. La selección múltiple manual usa las teclas del sistema/navegador. Los botones proporcionan condiciones constantes de comparación.

selectedOptions enumera valores DOM seleccionados, values es .val() del select y selectedAttribute son atributos presentes. form representa FormData como consulta URL, sin enviarla. changes cuenta manejadores; Set emite un evento por cada control, por tanto dos.

Estado actual y atributo inicial

option.selected y :selected describen el presente. [selected] comprueba el atributo; defaultSelected representa el predeterminado. Cambiar la selección no reescribe ese valor de igual modo. No use [selected] para consultar el estado actual.

.val(["css"]) cambia el presente y .val([]) vacía el múltiple. El setter .val() no dispara change, por eso el ejemplo lo emite explícitamente. Sin evento o render, el informe puede quedar antiguo aunque el control cambie.

Desde jQuery 3, un múltiple sin selección devuelve []. .val() de una colección option vacía es undefined. Un select simple sin opción tras asignar un valor desconocido da null. No son siempre cadenas vacías.

Reset llama form.reset() y render. Editar los atributos predeterminados cambiaría también el destino de reinicio. Aquí se mantienen y solo cambian los valores actuales.

Deshabilitados, :checked y aplicación

Opciones deshabilitadas, incluso dentro de optgroup deshabilitado, pueden seguir seleccionadas y quedar fuera de .val() del select y FormData. Cantidad seleccionada no es cantidad enviada: tres frente a uno al inicio. Revise también name ausente o select deshabilitado.

:checked cubre opciones, casillas y radios. Limitado a option:checked devuelve las mismas opciones aquí; globalmente puede mezclar tipos.

:selected es una extensión jQuery y no es válida directamente en document.querySelectorAll() nativo. El ejemplo selecciona por CSS y filtra :selected. En código nativo considere select.selectedOptions o un option:checked limitado.

Aplique colores y filtros una vez al iniciar y después al cambiar. Defina actualización para asignaciones programadas, muestre textos con .text() en vez de HTML concatenado y valide identificadores y reglas en el servidor.