ITECH Blog

Entrañas Sistemáticas

Combos dependientes con jQuery (AjAX)

with 15 comments

productshot_ajax

La necesidad de los Selects/Combos/Listas o como los desees llamar que colocamos en formularios web los cuales en alguna ocasion dependera su informacion de una lista previa es algo que tarde o temprano nos toca tener presente. Por ejemplo, el caso de un formulario web donde tenemos 3 listas (Pais, Estado y Ciudad) donde seleccionas el Pais y en base al pais seleccionado, el combo de Estado desplegara solo los estados de ese pais, e igual con sus Ciudades, solo las del Estado de ese Pais que ya se ha seleccionado. Y eso nos sirve para otros casos, una lista de Productos, el cual al seleccionarlo se nos despliegue en otra lista las categorias de ese Producto y hasta en otra lista unas subcategorias de esas categorias, todo proveniente de la base de datos.

Una muestra de lo que trata este articulo sobre listas dependientes. Pais: Venezuela – Estado: Zulia, es el unico que en este ejemplo tiene 3 ciudades.

Creamos una pagina PHP con un formulario el cual contendra 3 combos o listas las cuales eran (Pais, Estado y Ciudad). En la BD debemos tener 3 tablas Paises, Estados y Ciudades.

Pais (id_pais, pais), Estados (id_estado, estado, id_pais), Ciudades (id_ciudad, ciudad, id_estado, id_pais).

De la tabla Pais id_pais puede ser un Integer Auto_Incrementable (AI), en Estados igual el id_estado, y en Ciudades igual el id_ciudad, recordando no perder la relacion entre los Ids de cada tabla para saber que Ciudad pertenece a que Estado de que Pais, como bien ya se sabe. En internet puede conseguirse un archivo .sql con las tablas de Paises y sus Estados, archivo .sql que importariamos a nuestra BD.

En mi caso busque y consegui mucha informacion sobre AJAX para hacer esto de los combos dependientes, codificaciones completas y largas que realmente poseian inestabilidad en el sentido de que algunos ejemplos descargados ni siquiera funcionaban como lo indicaba su autor sin haberles modificado nada, otros eran funcional pero casi intocables, al tratar de adaptarlo a nuestra pagina o proyecto web, era mas el que fallara que el que funcionara como en su puro e inmodificable ejemplo descargado.

Excluyendo post propios de mi persona en este web blog, material educativo de terceros es comentado su link para hacer referencia al material de otros autores (sin en ningun momento acreditarse articulos o explicaciones ajenas) respetando los derechos de autor. En estos casos hago copia de apuntes de terceros en mi bloq porque ya me ha tocado situaciones en las que he perdido el link o incluso, URLs rotas tratando de volver a obtener dicha informacion al menos por los cache de google. Para evitarme estos mal percances pasados, coloco en mi blog las ensenanzas de otras partes para mantener una copia bien sea original o modificada de dicho articulo, lo cual sera para este caso.

Combos dependientes con jQuery

Encontre un material corto, entendible y muy factible en su practica que hace uso de la libreria de javascript jQuery, este material pertenece al blog de Miguel Manchego articulo titulado Combos dependientes AJAX Bases de Datos.

Primero debemos descargar de jquery.com la libreria javascript que nos ayudara a realizar estos combos dinamicos, de su seccion de descarga nos bajamos el jquery (descarga jquery), este archivo .js lo colocamos en la carpeta de nuestro proyecto web, bien sea dentro de una subcarpeta o en la carpeta raiz de nuestro proyecto web.

Debemos crear una pagina .php por cada combo dependiente, en este caso tenemos 3 combos (Pais, Estado y Ciudad), pero el combo Pais no es dependiente de ninguno previo, por lo que el llenado del 1er combo es como ya normalmente llenas un combo.

Yo por mi parte indico la conexion de la Bd en un archivo php el cual incluyo en las de paginas php.

conexion.php

<?php
function conectar(){
   $servidor = mysql_connect("localhost","usuario","clave") or die('Error de conexion al Servidor: ' . mysql_error());
   $basedatos = mysql_select_db("mi_basedatos") or die('Error de conexion con la BD: ' . mysql_error());
}
function desconectar(){
   mysql_close();
}
?>

Creamos nuestro formulario bien sea con algunos pocos campos de texto y 3 combos (Pais, Estado y Ciudad). Llenamos la lista de paises en el combo o lista Pais:

<?php
include 'conexion.php';
conectar();
$resultado = mysql_query("select * from paises");
if($fila = mysql_fetch_array($resultado)){
   do{
      echo '<option value="'.$fila['id_pais'].'">'.$fila['pais'].'</option>';
   }while($fila = mysql_fetch_array($resultado));
}
mysql_free_result($resultado);
desconectar();
?>

El bucle que usamos para cargar las listas debe ser un do{ }While() y no un While() porque la linea $registros = mysql_fetch_row($resultado) hace correr el cursor de la BD, por lo que con un bucle While() debe volverse a cargar la consulta SQL una vez dentro del IF() y antes del While(), al ejecutar dos veces la SQL esto vuelve lenta la traida de la data de la BD y para el caso de muchos usuarios conectados al sitio, la carga se vuelve muy lenta.

Si usasemos un  bucle While() el codigo seria este:

$consulta = "select * from tabla";
$resultado = mysql_query($consulta);
$registros = mysql_fetch_row($resultado);
if($registros){
   $resultado = mysql_query($consulta);
   while($fila = mysql_fetch_array($resultado)){
      echo '<option value="'.$fila['id'].'">'.$fila['campo'].'</option>';
   }
}

Con respecto a la linea azul,  el mysql_fetch_row() mueve el cursor de la BD al siguiente registro, si la SQL es filtrada donde buscamos un solo y unico registro, al llegar al While(), no traera datos porque mysql_fetch_row() movio el cursor de la BD y ahora la consulta para el While es nula. Si la SQL filtrada nos traera varios registros, faltara el primero para el While(). Si colocamos nuevamente luego del IF() la consulta SQL como se indica en las lineas rojas, estariamos ejecutando la consulta 2 veces que en un servidor localhost no se notaria la lentitud pero si en un servidor online de produccion y con muchos usuarios conectados a la pagina que carga los datos, dicha carga seria sumamente lenta por la recarga doble de la consulta.

La solucion para evitar que no se nos mueva el cursor de la BD al terminar la consulta es obviamente no usar el mysql_fetch_row() el cual mete en una matriz la data y nos ocasiona este desplazamiento del cursor a la siguiente fila. Tambien el que se debe usar es un do-while() y no un while() lo cual seria un haz-mientras mejor que un mientras() tal cosa. Asi se ejecuta el ciclo al menos una 1era vez y se evalua luego y asi sucesivamente y no evaluar primero antes de hacer el 1er ciclo y subsiguientes.

$consulta = "select * from tabla";
$resultado = mysql_query($consulta);
if($fila=mysql_fetch_array($resultado)){
  do{
     echo '<option value="'.$fila['id'].'">'.$fila['campo'].'</option>';
  }while($fila = mysql_fetch_array($resultado));
}

El codigo para cargar la lista de paises de la BD seria este:

$consulta = "select * from paises";
$resultado = mysql_query($consulta);
if($fila=mysql_fetch_array($resultado)){
  do{
     echo '<option value="'.$fila['id_pais'].'">'.$fila['pais'].'</option>';
  }while($fila = mysql_fetch_array($resultado));
}

Este codigo php iria inyectado entre <select id=”pais’><?php codigo ?></select> con lo cual ya en el formulario estariamos mostrando la lista de Paises, podemos culminar la SQL con un Order By pais o ASC o DESC para order la lista a nuestro gusto.

Para los otros 2 combos ya debemos recurrir a jquery y otras paginas php que debemos hacer. Recordando el que comentamos que por cada combo dependiente haremos una pagina php. En esta practica tenemos 2 combos dependientes que son Estado y Ciudad, por lo que crearemos una pagina para cada uno y ya veras a que se desea llegar con esto.

El mismo codigo php que usamos para cargar la lista de Paises podemos usarlo para cargar la lista de Estados en otro archivo, solo cambiaremos un poco la SQL y los campos, pero en esencia es la misma codificacion.

estados.php

<?php
   include 'conexion.php';
   conectar();
   $resultado = mysql_query("select * from estados where id_pais = '$_POST[elegido]'");
   if($fila = mysql_fetch_array($resultado)){
      do{
         echo "<option value=".$fila['id_estado'].">".$fila['estado']."</option>";
      }while($fila = mysql_fetch_array($resultado))
   }
   mysql_free_result($resultado);
   desconectar();
?>

Copiamos este codigo de que carga la lista de Estados y hacemos otro archivo php y lo modificamos nuevamente en la SQL y en los campos:

ciudades.php

<?php
   include 'conexion.php';
   conectar();
   $resultado = mysql_query("select * from ciudades where id_estado = '$_POST[elegido]'");
   if($fila = mysql_fetch_array($resultado)){
     do{
        echo "<option value=".$fila['id_ciudad'].">".$fila['ciudad']."</option>";
     }while($fila = mysql_fetch_array($resultado))
   }
   mysql_free_result($resultado);
   desconectar();
?>

Ahora solo nos queda indicar un pequeno codigo javascript en la pagina de nuestro formulario web php, este codigo javascript ira antes del <body> para que al cargarse la pagina, ya se haya cargado el codigo javascript.

<script language="javascript" src="jquery-1.3.2.min.js"></script>
<script language="javascript">
  $(document).ready(function(){
     $("#cmbpais").change(function () {
        $("#cmbpais option:selected").each(function () {
           elegido=$(this).val();
           $.post("estados.php", { elegido: elegido }, function(data){
              $("#cmbestados").html(data);
              $("#cmbciudades").html("");
           });
        });
     })

     // Este puede ponerse en comentario si no se dispone de un 3er combo:
     $("#cmbestados").change(function () {
        $("#cmbestados option:selected").each(function () {
           elegido=$(this).val();
           $.post("ciudades.php", { elegido: elegido }, function(data){
               $("#cmbciudades").html(data);
           });
        });
     })

  });
</script>

Hemos marcado en verde donde llamos al archivo .js jquery e indicamos en negrita la funcion padre la cual contiene 2 subfunciones, y colocamos en azul una de las 2 subfunciones porque si solo tenemos 1 solo combo dependiente, la linea indicada en rojo y el codigo en azul no estarian, en cambio si tenemos 2, 3, 4, etc combos dependientes uno dependiente del previo, copiamos y pegamos mas abajo el codigo de una de las subfunciones y editamos a que combo previo pertenece, a que archivo .php llamara la carga de los datos y a que combo se cargaran los datos.

 


Funcion signo dolar $: En el codigo de javascript el signo $ es un atajo mejorado de la funcion document.getElementById(). Si se le pasa una cadena de texto con el identificador de un elemento, obtiene ese elemento. La función admite uno o más parámetros: si se le pasa un parámetro, devuelve un objeto; si se le pasan varios parámetros, devuelve un array simple con todos los objetos.

 

/ Con JavaScript
var elemento = document.getElementById(‘primero’);
// Con Prototype
var elemento = $(‘primero’);
// Con JavaScript
var elemento1 = document.getElementById(‘primero’);
var elemento2 = document.getElementById(‘segundo’);
// Con Prototype
var elementos = $(‘primero’, ‘segundo’);

Existen muchas otras funciones como $F() que permite obtener directamente el valor de los campos de formulario, $$() que permite seleccionar elementos de la pagina utilizando selectores CSS, la funcion $A() para convertir en array (cualquier cosa que se parezca a un array), $R() para crear rangos de valores. El rango de valores se crea desde el valor del primer argumento hasta el valor del segundo argumento. El tercer argumento de la función indica si se excluye o no el último valor (por defecto, el tercer argumento vale false, que indica que sí se incluye el último valor).

Debemos aprender AJAX puesto que es el faltante en el desarrollo web para que las aplicaciones web obtengan una interaccion presente en las aplicaciones de Escritorio (no presentes en las de ambiente web),  Ajax es ese complemento que hacia falta.

 


Cuando ya tenemos datos en los 3 combos, si cargamos otro pais (select padre) la informacion de estados se reemplazara inmediatamente por la nueva data y el combo de ciudades se limpiara, como se indica en la linea de codigo marcada en rojo.

Nos fijamos que los <select> de Estado y Ciudad no poseen <option> en el formulario ya que estos se encuentran en estados.php y en ciudades.php dentro del bucle o ciclo while php, igual como en que llena la lista de Paises, codigo que no se llama de otro archivo sino que esta ya incluido entre lineas del codigo html de la pagina de formulario. Al cargarse la pagina de formulario ya se ha cargado el codigo javascript el cual por un evento change envia via post el dato seleccionado del combo a estados.php el cual busca los datos por una SQL filtrada por una variable elegido presente en el codigo javascript y la cual se observa en la SQL $_POST[elegido] (post de javascript, no post del formulario). Entonces el codigo javascript envia el dato a estados.php o ciudades.php bien sea el caso del combo previo seleccionado y devuelve a la pagina de formulario los datos en el combo.

 

Yo llame a las paginas estados.php y ciudades.php por el contenido que tendrian, pero asi como en las indicaciones y codigo de Miguel comentado al comienzo del post, puedes ponerles combo2.php y combo3.php ajustando esto en el Id de los <select> y en el codigo javascript, queda al gusto de cada quien el nombre de los objetos y los archivos.

enjoy!

Anuncios

Written by jocdz

noviembre 5, 2009 a 4:07 pm

Publicado en AJAX, jQuery, MySQL, php, Web

15 comentarios

Subscribe to comments with RSS.

  1. Wow, solo lo he leido y esta muy bien explicado muchas felicidades, aun no lo he probado pero tengo la corazonada que funcionará, precisamente vengo de leer la web de manchego y no me quedo muy claro pero con tu estupenda explicación se ve muy sencillito.

    Gracias por regalarnos un poco de tu tiempo ayudandonos sigue así.

    furiaroa

    diciembre 19, 2009 at 7:14 am

    • Gracias furiaroa, yo por mi parte claro seguire posteando lo que consiga y comprenda y de igual forma exprese mi entendimiento y asi como uno va conociendo las cosas en el camino abriendose paso para que dicho camino quede algo mas despejado y transitorio para otros, ya que todos recibimos de igual forma lo que necesitamos y buscamos en muchas otras partes, blogs, etc.

      Pero cambie a otro blog (algun capricho raro supongo) y algunos post me los copie y dejo otros aqui de recuerdo en caso de necesitarse alguna informacion.

      Mismo post pero al final con un link de descarga del ejemplo:
      http://1024bytes.wordpress.com/2009/12/10/selects-dependientes/

      salduos.

      j053d

      diciembre 19, 2009 at 1:18 pm

  2. Me gustaria saber como hago para insertar esos combos seleccionados a la base de datos en mysql….

    David James

    febrero 12, 2010 at 6:27 am

  3. hola!

    ya no vigilo este blog, ahora estoy en esta otra direccion, te indico la url donde nuevamente esta este post y el cual tiene un link de descarga con lo que necesitas, slaudos.

    http://j053d.net/blog/selects-dependientes/

    j053d

    febrero 13, 2010 at 12:35 am

  4. Hola!.. gracias por el aporte, la verdad andaba buscando algo asii.. y tu post vino a solucionar mi problema:) gracias!

    Eldita Sonoqui

    septiembre 17, 2010 at 5:51 am

  5. El ejemplo esta muy bien explicado, ya quedo mi pagina para filtrar tipificaciones.

    Tengo una duda por medio de un For se generan varias filas, y en cada una de ellas necesito realizar ese mismo filtro y que segun lo que seleciones me traiga en los resultados en el segundo filtro, es el mismo ejemplo que nos muestra pero en varios registros ó filas, pero esta labor se hace en el mismo formulario

    Agradezco sus comentarios

    Robinson

    mayo 4, 2011 at 4:40 pm

  6. Esto no funciona en IExplorer no se reconoce la funcion .change ya he tratado mucho con jquery cachando el tipo de navegador, haciendo una funcion y llamandola en el onchange del mismo select. Alguien podria ayudarme?

    juan

    agosto 3, 2011 at 5:50 am

  7. excelente aporte

    leonardo

    mayo 6, 2012 at 5:12 pm

  8. Hola, la verdad que que buen aporte, me acabas de sacar de un gran embrollo, aplique tus codigos y funcionarion muy bien, muchas gracias =)….pero donde tengo un pequeño problema es al querer mostrar los datos que ya eh almacenado en otra tabla aparte, por medio de un formulario, y lo que necesito es mostrar los datos tal cual para poderlos modificar en un formulario identico al de insertar . espero me puedas ayudar

    Monica

    septiembre 6, 2012 at 6:33 pm

  9. Hola, tengo un problema donde defino la variable “elegido” ya que me indica ese error en ‘$_POST[elegido]’ de la carga de los datos al select…

    Espero tu respuesta
    Muchas gracias….

    Milton Miño

    octubre 1, 2012 at 5:43 pm

  10. hola …. a mi me pasa algo parecido…resulta que lleno una lista con una consulta sql y despues deseo utilizar un valor que seleccione de esa lista para hacer otra consulta y filtrarla por el valor que seleccione…pero no me toma el dato que selecciono de la lista que cargue y me genera un error en la segunda consulta que hago…creo que para eso necesito el script que colocaste pero no lo entiendo…agradesco si me pueden ayudar
    gracias

    dhiego

    octubre 2, 2012 at 3:06 pm

  11. noob

    cabezas

    diciembre 14, 2012 at 8:38 pm

  12. wballesteros.wordpress.com Aca esta mejor explicado 😀

    wballesteros

    diciembre 14, 2013 at 1:47 am

  13. Excelente material, de gran ayuda, felicitaciones!!

    Marco

    mayo 31, 2017 at 4:53 pm


Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s

A %d blogueros les gusta esto: