Ejemplo de 3 Listas Desplegables con PHP y AJAX usando GET
Hace un tiempo, recibí un correo de un lector desde México, donde me contaba que estaba haciendo un proyecto y que había leído los casos mostrados de las listas desplegables, necesitaba utilizar 3 listas y todo con AJAX, luego de coordinar el envío de archivos procedí a ayudarlo, los datos estaban en un archivo plano (conocido también como archivo texto o de notepad), luego de migrar a una base de datos, no la normalicé como debía ser, hice todo en una sola tabla, en este caso MySQL, preparé los scripts que paso a hacerlo público y espero sea de utilidad para todos.
La idea es ver los códigos postales de cada sitio, para lo cual hay que llegar hasta ellos, seleccionando primero el Estado a donde pertenece, luego la Delegación Municipal y finalmente la Colonia.
La estructura de la tabla es:
CREATE TABLE 'codigos' ( 'id' int(10) NOT NULL auto_increment, 'estado' varchar(30) default NULL, 'cp' varchar(6) default NULL, 'colonia' varchar(50) default NULL, 'delemuni' varchar(30) default NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=78322 ;
Como ven en el auto_increment, cuenta la tabla códigos con bastantes registros, y esto nos servirá para ver lo práctico del uso de AJAX, empecemos.
Para poder mostrar los datos en HTML, creamos una tabla
listasejemplo.html
<table border="1" width="40%" bgcolor="#FFFFCC"> <tbody> <tr> <td width="20px">Estado:</td> <td><select id="sEst"></select></td> </tr> <tr> <td>Delemuni:</td> <td><select id="sDM"></select></td> </tr> <tr> <td>Colonia:</td> <td><select id="sCol"></select></td> </tr> <tr> <td>Cod.Postal:</td> <td><select id="sCP" size="10"></select></td> </tr> </tbody></table>
Cada select está identificado con si respectivo id para poder acceder a él mediante DOM, las listas están vacías todas las llenaremos con AJAX; seguidamente crearemos el objecto XMLHTTPRequest, como sabemos esto es mediante javascript, y nos permitirá ejecutar el código en cualquier navegador y versión, el código sería:
// creando objeto XMLHttpRequest de Ajax var obXHR; try { obXHR=new XMLHttpRequest(); } catch(err) { try { obXHR=new ActiveXObject("Msxml2.XMLHTTP"); } catch(err) { try { obXHR=new ActiveXObject("Microsoft.XMLHTTP"); } catch(err) { obXHR=false; } } }
Ahora si tenemos éxito creando el objeto obXHR, necesitamos que cuando hagamos click en cada lista desplegable y escojamos un elemento llene la lista siguiente con datos filtrados de las tablas, para esto creamos una función javascript cargar, esta recibirá dos parámetros, el script php que se ejecutará mediante AJAX y que nos dará los datos y que objeto HTML contendrá los datos siguientes, el script sería:
function cargar(url,obId) { var obCon = document.getElementById(obId); obXHR.open("GET", url); obXHR.onreadystatechange = function() { if (obXHR.readyState == 4 &amp;&amp; obXHR.status == 200) { obXML = obXHR.responseXML; obDes = obXML.getElementsByTagName("descri"); obCon.length=obDes.length; for (var i=0; i<obdes .length;i++) { obCon.options[i].value=obDes[i].firstChild.nodeValue; obCon.options[i].text=obDes[i].firstChild.nodeValue; } } } obXHR.send(null); }
Para nuestro caso el script PHP va a ser el mismo cuando hagamos clic en cada lista, en el script llamaremos a una clase que debería estar en otro archivo y llamarla con un include, pero por motivos pedagógicos y de estudio está en el mismo archivo, esta clase contiene 3 propiedades y 3 métodos, las propiedades nos permitirán manejar todo lo relacionado a los datos y los métodos a la conección, a seleccionar la base de datos, cerrarla, y también las consultas a la tabla.
cargar.php
class cargar { var $cn; var $rs; var $sql;</strong> <strong>function __construct($sql) { $this->sql=$sql; $this->cn = mysql_connect("localhost","usuario","clave"); mysql_select_db("basededatos"); $this->cargar(); }</strong> <strong>function cargar() { $this->rs=mysql_query($this->sql); header('Content-Type: text/xml'); echo "\n"; echo "\n"; echo "Seleccione"; while (list($descri) = mysql_fetch_row($this->rs)){ echo "$descri\n"; } echo "\n"; }</strong> <strong>function __destruct() { mysql_close($this->cn); } } // fin de la clase cargar extract($_GET);</strong> <strong>if (isset($est)) { $sql = "SELECT DISTINCT delemuni FROM codigos WHERE estado='$est' ORDER BY delemuni"; }elseif (isset($dm)) { $sql = "SELECT DISTINCT colonia FROM codigos WHERE delemuni='$dm' ORDER BY colonia"; }elseif (isset($col)) { $sql = "SELECT DISTINCT cp FROM codigos WHERE colonia='$col' ORDER BY cp"; }else { $sql = "SELECT DISTINCT estado FROM codigos"; }</strong> <strong>$clCar = new cargar($sql);
Luego de la clase tenemos la sentencia extract, lo que hace es convertir a variables todo lo que mandemos como método GET, según la lista iremos usando diferentes consultas SQL a la tabla.
Finalmente agregamos eventos onchange a las listas quedaría así cada una:
<select id="sEst" onchange="cargar('cargar.php?est='+this.value,'sDM')"></select> <select id="sDM" onchange="cargar('cargar.php?dm='+this.value,'sCol')"></select> <select id="sCol" onchange="cargar('cargar.php?col='+this.value,'sCP')"></select>
y por último necesitamos que la primera lista se cargue junto con la página, por lo que usaremos el evento onload de la etiqueta body
<body onload="cargar('cargar.php','sEst')">
Nice site ….)
Hey, I am checking this blog using the phone and this appears to be kind of odd. Thought you’d wish to know. This is a great write-up nevertheless, did not mess that up.
– David
Hola he utilizado este codigo y hace las consultas ok….pero a la hora de utilizar estos datos para hacer envio no puedo, ya que utilizado el metodo «action» para cargar los datos ahora como hago para enviarlos?
I want to quote your post in my blog. It can?
And you et an account on Twitter?
Glad to share your articles, let me learn more knowledge
Tengo un error y es que quiero que al pulsar un select llamado estado, seleccione una empresa, y al pulsar la empresa me liste en un select sus productos, y en otro select el nombre del vendedor de esa zona. Podría alguno ayudarme, por favor. Gracias..!!
Amigo he analizado ke una depuración del codigo sería… seleccionar específicamente el código para esa ciudad de ese estado…
Lo que hace tu codigo (un error por asi decirlo)… es que TOMA CUALQUIER COLONIA QUE SE LLAME «X» y saca TODOS LOS CODIGOS POSTALES POSIBLES…
Ejemplo: La colonia Framboyanes existe en más de un Estado de la Republica.
Tu código saca todos los códigos postales de la Col. Framboyanes en todos los estados… Y ESO NO NOS INTERESA…
Nos interesa nadamas LA COLONIA DEL ESTADO INDICADO DE LA CIUDAD INDICADA.
Esto pasa porque al enviar la consulta PIERDES LOS PARAMETROS DEL ESTADO Y LA CIUDAD AL QUE PERTENECE LA COLONIA QUE ESTAS INDICANDO EN LAS LISTAS.
Habría que pasar en la última consulta… el parámetro del Estado y la Ciudad al AJAX, para poder hacer la consulta en PHP más específica:
Por ejemplo la consulta la tienes así en la línea 36:
$sql = «SELECT DISTINCT cp FROM codigos WHERE colonia=’$col’ ORDER BY cp «;
Esto nos extrae TODOS LOS CODIGOS DE TODAS LAS COLONIAS CON ESE NOMBRE. COSA INCORRECTA!
Lo Correcto sería que nuestra consulta final fuera algo así:
$sql = «SELECT DISTINCT cp FROM codigos WHERE colonia=’$col’ AND ciudad=’$ciudad’ AND estado=’$estado’ ORDER BY cp «;
O sea, pasándole el parámetro de ESTADO y CIUDAD, para hacerla más específica.
Pero aún no se como hacerlo, lo estoy analizando…
Muchas gracias amigo por los archivos… aunque creo que la base de datos de los codigos postales no esta muy bien capturada…
Yo estoy depurando la tabla… en cuanto la finalize la comparto…
Gracias !
Oie amigo.. gracias por el aporta esta super bueno el ejemplo…
Me gustaria saber si podrias facilitarme los archivos de ejemplo con los codigos postales…
Gracias !…