La Página de DriverOp

Listas dependientes, segunda parte.

En este artículo volveré a abordar el problema de hacer que dos listas tipo select (o listbox) sea dependiente el segundo respecto del primero, es decir que el segundo select cambie de valores dependiendo del valor seleccionado en el primero, pero esta vez implementado con Ajax de JQuery y base de datos.

Introducción.

En el artículo original implementé una solución que se basa en que la fuente de datos para los selects es un archivo de texto y la ejecución es sincrónica. En este artículo se verá una solución diferente. La implementación se hará usando Ajax de JQuery y la funte de datos será una base de datos, todo con programación en PHP del lado del servidor.

Tal como en el artículo original, en esta la solución se usará como ejemplo un selector de países y otro de regiones o províncias que permitirá al visitante seleccionarla según el país que haya elejido en el primero.

La mecánica será como sigue: El select con los países se cargará directamente de la base de datos, el select de regiones se cargará mediante Ajax también usando la base de datos aprovechando la implementación que JQuery ofrece.

He elejido JQuery por ser simple de usar y porque su uso está suficientemente extendido además de estar muy bien documentado (si se sabe inglés, claro).

Como la implementación requiere de base de datos, lo primero que hay que hacer es construir las tablas.

Tablas países y regiones:

A continuación las tablas "paises" y "regiones":

paises
idnombre
1Argentina
2Colombia
3México
regiones
idid_paisnombre
11Buenos Aires
21Córdoba
31Entre Ríos
42Distrito Capital
52Atlántico
62Antioquía
73Distrito Federal
83Michoacán
93Monterrey

Esto no requiere mucha explicación. Las tablas contienen lo mínimo necesario y sirven nada más que como ejemplo. El campo "id_pais" de la tabla "regiones" es el índice de la tabla "paises" al cual la región pertenece.

El código HTML y PHP

.

La página HTML donde se implementará esto debe ser como mínimo de esta forma:







País:

Región:

El <?php while ($fila = mysql_fetch_assoc($result)) { echo sprintf('',$fila['id'],$fila['nombre']); } ?>

Región:

<?php mysql_close($link); // Nunca olvides cerrar la conexión a la base de datos. ?>

Esto generará efectivamente las opciones del primer select con los países.

Como la implementación requiere una forma de generar dinámicamente el segundo select y esto deberá hacerse mediante una petición Ajax, hay que escribir un script PHP que haga justamente esto el cual será el objetivo de la petición Ajax.

Este script no hará más que escribir un option por cada región que haya en la tabla "regiones" con una salvedad, solamente lo hará dependiendo de un valor que se pasa por $_GET que será el índica "id" del país cuyas regiones se quieren mostrar. A este script lo llamaré "makeselect2.php". El código es el siguiente:

<?php
	$idpais = $_GET['pais'];
	$link = mysql_connect("localhost", "myusername", "mypassword", true); // <-- debes cambiar por tus datos de acceso a MySQL.
	mysql_select_db("test", $link); // <-- debes cambiar "test" por el nombre de tu base de datos en MySQL.
	mysql_query("SET NAMES UTF8",$link);
	$sql = "SELECT * FROM `regiones` WHERE `id_pais` = ".mysql_real_escape_string($idpais)." ORDER BY `nombre`";
	$result = mysql_query($sql,$link);
	echo '';
	mysql_close($link);
?>

El parámetro en $_GET se llamará convenientemente "pais". Ese dato lo usamos al construir la sentencia SQL haciéndola pasar por la función mysql_real_escape_string() para evitar (o más bien aliviar) los ataques por SQL Injection.

Podrás notar además que estoy ejecutando una sentencia SQL algo extraña inmediatamente después de hacer la conexión: SET NAMES UTF8. Lo que esto hace es establecer la conexión a la base de datos en la tabla de caracteres UTF8, esto sirve para que los caracteres especiales no-ASCII se impriman correctamente en la página (especialmente las vocales asentuadas y las "ñ" en español).

Entra JQuery.

Bien pues, tenemos todo listo para hacer que las cosas funcionen.

El lector podría pensar que se puede generar el sergundo select "region" directamente en el código de la página pero dos razones atentan contra esto. La primera es metodológica. Aunque se haga esto, se requerirá del script "makeselect2.php" de todos modos con la consecuencia de que se estará repitiendo código. La otra es práctica. Quien sepa JQuery sabrá que se puede ejecutar la petición Ajax inmediatamente después de que la página se cargue haciendo uso del evento .ready() de JQuery. De esta forma no se repite código y tiene el agregado de que podemos establecer el valor por omisión del select "selector1" a la opción que queramos sin necesidad de cambiar nada más en el resto del código.

Al código HTML ya visto vamos a agregar la sección

Primero se carga la biblioteca JQuery. Luego ejecutamos .ready() en el objeto document. Sobre el elemento "sel2" (que es un en el código HTML) ejecutamos la petición Ajax que en JQuery es el método .load() al cual le pasamos como parámetro la dirección del script "makeselect2.php" adosándole como parámetro GET "pais" el valor actual del select "selector1" mediante la llamada al método .val() que nos proporciona JQuery.

El metodo .load() de JQuery aplicado sobre un elemento funciona rellenando ese elemento con el resultado que el servidor envia al llamar al script correspondiente.

Y aquí tengo que hacer una aclaración. Parece poco intuitivo que haya usando un como contenedor del select y que además "makeselect2.php" genere todo el tag . De forma tal que hacer esto:

	document.getElementById("selector2").innerHTML = "";

No funciona.

Internet Explorer simplemente no hace nada con "selector2" cuando es un elemento "selector2" y que "makeselect2.php" genere no solo los