Si los
<select>
cargarán la información de manera dinámica, es decir, elegirás una opción del primer
<select>
y luego tendrán que cargar opciones relacionadas a dicha opción pero en el segundo
<select>
y la misma situación será con el segundo y tercer
<select>
, puedes hacer lo que explicaré a continuación.
1. Dentro del formulario, añade tres secciones:
2. Crea una función que realizará las respectivas peticiones asíncronas (
AJAX) para obtener los datos de la base de datos con los cuales armarás los
<select>
:
Código Javascript
:
Ver originalvar ajax = function(opciones){
var xhr = new XMLHttpRequest(),
url = "tuArchivo.php?nivel=" + opciones.nivel;
if (opciones.valor){
url += "&valor=" + opciones.valor;
}
xhr.open("GET", url, true);
xhr.send();
xhr.addEventListener("load", function(){
if (this.status == 200){
opciones.seccion.innerHTML = this.responseText;
}
}, false);
};
3. Crea el
script en el archivo PHP que procesará esta petición, realizará la búsqueda en la base de datos y creará el respectivo
<select>
:
Código PHP:
Ver original<?php
$conexion = new mysqli('servidor', 'usuario', 'clave', 'base de datos');
if ($conexion->connect_errno) exit($conexion->connect_errno . ': ' . $conexion->connect_error);
$nivel = $conexion->real_escape_string(strip_tags(trim($_GET['nivel']))); $valor = isset($_GET['valor']) ?
$conexion->real_escape_string(strip_tags(trim($_GET['valor']))) : '';
$campoCodigo = 'tabla' . $nivel . '_codigo';
$campoNombre = 'tabla' . $nivel . '_nombre';
$campoClave = 'tabla' . $nivel . '_campoClave';
$tabla = 'tabla' . $nivel;
$consulta = "SELECT $campoCodigo, $campoNombre FROM $tabla";
$consulta .= " WHERE $campoClave = '$valor'";
}
$resultados = $conexion->query($consulta) or
exit($conexion->error);
if ($resultados->num_rows){
?>
<select class="combo">
<?php
while($registros = $resultados->fetch_assoc()){
?>
<option value="<?=$registro[$campoCodigo]?>"><?=$registro[$campoNombre]?></option>
<?php
}
$resultados->free();
?>
</select>
<?php
}
$conexion->close();
4. Para que el primer
<select>
aparezca luego de haber cargado la página, necesitas hacer la llamada a la función
ajax()
pasándole los respectivos valores. Esto se ejecutará luego de ocurrido el evento
DOMContentLoaded
el cual se dispara cuando han terminado de cargar los elementos del documento:
Código Javascript
:
Ver originaldocument.addEventListener("DOMContentLoaded", function(){
ajax({
nivel: 1,
seccion: document.querySelector("#ejemplo section") //Por defecto, toma a la primera
});
}, false);
5. Para realizar las llamadas por cada vez que se elija un valor en cualquiera de los
<select>
y ya que estos cargarán de manera dinámica, debes asociar el evento
change
al documento, de tal forma que al ocurrir, tomas al elemento en el cual se produjo el evento y podrás enviar los datos que le correspondan:
Código Javascript
:
Ver originaldocument.addEventListener("change", function(event){
if (event.target.className == "combo"){
ajax({
nivel: [].indexOf.call(document.querySelectorAll(".combo"), event.target) + 1,
seccion: event.target.parentNode,
valor: event.target.value
});
}
}, false);
6. Cuando ya tengas a los tres
<select>
y hayas seleccionado las respectivas opciones, puedes proceder a realizar el redireccionamiento, para lo cual tendrás que cancelar el evento
submit
el cual ocurre cuando se inicia el envío de los datos del formulario. Para esto, deberás utilizar el método
.preventDefault()
:
Código Javascript
:
Ver originaldocument.querySelector("#ejemplo").addEventListener("submit", function(event){
event.preventDefault(); //Cancelamos el envío
var combos = document.querySelectorAll(".combo"),
direccion = "http://www.ejemplo.com/" + combos[0].value + "/" + combos[1].value + "/" + combos[2].value;
location = direccion;
}, false);
Todo el código JavaScript debe quedar junto y en el orden descrito, es decir:
Código Javascript
:
Ver originaldocument.addEventListener("DOMContentLoaded", function(){
//Punto 2
//Punto 4 (solo la llamada a la función)
//Punto 5
//Punto 6
}, false);
En resumen, tenemos tres secciones dentro del formulario en las que cargarán los tres
<select>
. Al terminar de cargar la página, se llamará a la función
ajax()
a la cual se le pasarán los valores del nivel (número de
<select>
) y la sección en la cual aparecerá. Dichos datos se pasan a la función a través de un objeto literal. En la función, se crea una instancia del objeto
XMLHttpRequest
para realizar la petición asíncrona (AJAX), se reciben los valores y si se ha recibido el valor a tratar en la condición de la consulta a la base de datos, se lo adhiere a cadena de consulta y la ruta del archivo PHP. Se realiza el envío y cuando se reciba la respuesta, se la mostrará en la sección que se haya designado.
En el archivo PHP, se realiza la conexión a la base de datos, se verifica si no se realizó para terminar la ejecución del
script y se reciben y
limpian los datos recibidos. Así como en la función
ajax()
, se verifica si se recibió el valor para la condición de la consulta SQL. Enseguida, se procede a elaborar la consulta, se la ejecuta y si se obtienen resultados, se procede a crear al respectivo
<select>
, el cual tendrá por clase el valor "combo" y se le asignarán las opciones según los registros obtenidos de la consulta a la base de datos. Finalmente, dicho
<select>
será la respuesta que recibirá la función
ajax()
y que mostrará en la sección respectiva.
Para este ejemplo, he supuesto que los nombres de las tablas de la base de datos tienen la forma "tabla", seguido del número de tabla según corresponde a cada
<select>
, esto con el fin de reutilizar el mismo
script para realizar distintas consultas a la base de datos, por lo que si los nombres de tus tablas no tienen una forma similar, te sugiero hacerlo de un modo parecido o quizá de otra forma que creas conveniente pero que se adapte al algoritmo propuesto. También puedes tener distintos archivos PHP para elaborar cada
<select>
, pero sería algo poco eficiente y elegante. Si deseas, puedes utilizar una clase para el tratamiento de los datos en el lado del servidor; por ejemplo, una clase con un método para realizar la conexión, otro para
limpiar a los datos recibidos, otra para armar la consulta SQL, otra para ejecutarla, y así.
La delegación del evento
change
al documento se debe a que no puedes registrar un evento a un elemento que ha cargado después de que haya cargado el documento, como ocurre en los casos de los
<select>
y otros elementos cargados dinámicamente, por lo que utilizar una clase en común, puede ser de mucha ayuda, como en este caso.
Para obtener al elemento en el que ocurrió el evento, debes acceder a él mediante la propiedad
target
del
objeto del evento. Para obtener a la sección que contiene al
<select>
en el cual se ha cambiado el valor, debes acceder a ella mediante la propiedad
parentNode
. Para obtener al nivel, es decir, el número de
<select>
en el cual ha ocurrido el cambio de valor, debes utilizar una instancia del método
.indexOf()
, el cual devuelve la posición del elemento en cuestión dentro de —en este caso— la lista de nodos cuya clase es "combo", empezando desde la posición cero, razón por la cual le sumo 1. La lista de nodos es devuelta por el método
.querySelectorAll()
.
Como se trata de un ejemplo, tienes que adaptarlo a lo que necesitas. Si tienes alguna duda, coméntala por aquí.
TIP DE AYUDA: Si quieres utilizar otro valor para los
<select>
que no sea el valor que estos toman de la opción seleccionada, puedes utilizar
atributos personalizados.
Un saludo