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