Modificar el contenido de un select a partir del otro sin Ajax

Programación

Tengo un listado de actividades que puedo filtrar con unos select. Tengo un campo select con lugares y otro con categorías que me harían de filtro. El tema es que hay categorías que no están en determinados lugares, así que no tiene sentido que se muestren si hemos preseleccionado un lugar.

El filtro inicial sería así, usando bootstrap para el código HTML:

<form method="get">
  <div class="card-header">FILTRA EL LISTADO</div>
  <div class="card-body">
    <div class="row">
      <div class="col-sm-4">
         <div class="form-group">
          <select name="destino" id="destino" class="form-control">
            <option value="">Por Destino</option>
            <option value="Cuenca">Cuenca</option>
            <option value="Madrid">Madrid</option>
            <option value="Ávila" >Ávila</option>
          </select>
        </div>
      </div>
      <div class="col-sm-4">
        <div class="form-group">
          <select name="categoria" id="categoria" class="form-control">
            <option value="">Por categoría</option>
            <option value="Canoas" >Canoas</option>
            <option value="Escalada" >Escalada</option>
            <option value="Hidropedales">Hidropedales</option>
            <option value="Piraguas" >Piraguas</option>
            <option value="Tiro con Arco">Tiro con Arco</option>
            <option value="Paddle surf" >Paddle surf</option>
          </select>
        </div>
      </div>
      <div class="col-sm-4 text-center">
        <input type="submit" value="Filtrar" class="btn btn-info">
      </div>
    </div>
  </div>
</form>

Todos estos datos los saco de la base de datos y, obviamente, hay muchas más actividades. El tema es que, por ejemplo no hay Escalada en Madrid o no hay hidropedales en Cuenca así que lo normal sería que cuando cambio el desplegable de destino, cargase por ajax las categorías de ese destino. Otra carga a la base de datos.

Eso nos lo podemos evitar con un poco de javascript y modificando ligeramente el html. Al mismo le pondremos unos data-lugar que nos indican a donde corresponde cada valor del desplegable.

<form method="get">
  <div class="card-header">FILTRA EL LISTADO</div>
  <div class="card-body">
    <div class="row">
      <div class="col-sm-4">
         <div class="form-group">
          <select name="destino" id="destino" class="form-control">
            <option value="" data-lugar="">Por Destino</option>
            <option value="Cuenca" data-lugar="cuenca">Cuenca</option>
            <option value="Madrid" data-lugar="madrid">Madrid</option>
            <option value="Ávila" data-lugar="avila">Ávila</option>
          </select>
        </div>
      </div>
      <div class="col-sm-4">
        <div class="form-group">
          <select name="categoria" id="categoria" class="form-control">
            <option value="" data-lugar="">Por categoría</option>
            <option value="Canoas" data-lugar="madrid,avila">Canoas</option>
            <option value="Escalada" data-lugar="cuenca">Escalada</option>
            <option value="Hidropedales" data-lugar="madrid,avila">Hidropedales</option>
            <option value="Piraguas" data-lugar="avila,cuenca">Piraguas</option>
            <option value="Tiro con Arco" data-lugar="madrid">Tiro con Arco</option>
            <option value="Paddle surf" data-lugar="madrid,avila">Paddle surf</option>
          </select>
        </div>
      </div>
      <div class="col-sm-4 text-center">
        <input type="submit" value="Filtrar" class="btn btn-info">
      </div>
    </div>
  </div>
</form>

Cada categoría puede tener uno o varios destinos asociados separados por comas.

Y esto lo acompañamos de un javascript que haga el filtrado

<script>
document.addEventListener('DOMContentLoaded', function() {
  // detectar cambios en el primer select
  var lugarSelect = document.getElementById('destino');
  var catSelect = document.getElementById('categoria');
  
  lugarSelect.addEventListener('change', function() {
    // obtener el valor de data-lugar del elemento seleccionado
    var lugarSeleccionado = lugarSelect.options[lugarSelect.selectedIndex].getAttribute('data-lugar');
    
    // mostrar todas las opciones si se selecciona "Por Destino"
    if (lugarSeleccionado === undefined) {
      for (var i = 0; i < catSelect.options.length; i++) {
        catSelect.options[i].style.display = 'block';
      }
    } else {
      // ocultar las opciones del segundo select que no pertenecen a ese lugar
      for (var i = 0; i < catSelect.options.length; i++) {

        if (catSelect.options[i].getAttribute('data-lugar') && catSelect.options[i].getAttribute('data-lugar').indexOf(lugarSeleccionado) === -1) {
          catSelect.options[i].style.display = 'none';
        } else {
          catSelect.options[i].style.display = 'block';
        }
      }
    }
  });
});
</script>

El resultado sería algo como esto

FILTRA EL LISTADO

Deja un comentario