Combos encadenados con JQuery Cascade
- Detalles
- Publicado: Domingo, 19 Octubre 2008 03:00
Una tarea muy común en los formularios HTML es poder "encadenar" distintos combos. Un ejemplo clásico sería la "ubicación geográfica" de un usuario: tres combos relacionados, con "Pais", "Provincia" y "Ciudad", los cuales tendrían que adaptarse automáticamente a la selección del combo anterior.
Realizar a mano esta tarea es algo bastante tedioso... y si la solución implica refrescar la página constantemente, también pasa a ser algo molesto para el usuario. Por suerte, la gente de JQuery nos va a facilitar las cosas. Y mucho. Veamos juntos cómo podríamos resolver ese mismo ejemplo.
JQuery Cascade
JQuery es una librería JavaScript que simplifica la manera de interactuar con los elementos HTML, manejando eventos y haciendo facil el usar técnicas como AJAX. Y lo mejor, es sumamente extensible a través de montones de plugins.
Uno de estos plugins es JQuery Cascade, que permite encadenar combos de manera muy fácil.
Con JQuery Cascade uno declara los combos en HTML, de manera común. Luego, con el API de JQuery, indicamos qué combos son encadenados, y de dónde se sacarán los datos para llenarlo. Así, cuando el usuario seleccione un elemento del combo, se disparará un evento para cargar los valores de los combos asociados.
De hecho, JQuery Cascade permite encadenar otros elementos HTML, y no sólo combos.
¿Y cómo funciona?
Con JQuery Cascade se declaran los combos de manera común, y luego se "encadenan" usando el API provisto. Al encadenar, se indica la URL que devolverá el contenido del combo. JQuery Cascade enviará un parámetro llamado val a esa URL, con el valor seleccionado por el usuario en el combo "padre".
La URL tiene que devolver los datos en el siguiente formato:
[{'When':'CODIGO','Value':'VALOR','Text':'DESCRIPCION'},{...},{...}]
Entonces, supongamos los siguentes dos combos:
<select id="pais"> <option value="AR">Argentina</option> <option value="ES">España</option> <option value="MX">Mexico</option> </select> <select id="provincia"></select>
El script para encadenarlos con JQuery Cascade es muy simple:
<script type="text/javascript"> $(document).ready(function() { $("#provincia").cascade("#pais",{ ajax: {url: '/BusquedaDeProvinciasPorPais'}, template: commonTemplate, match: commonMatch }); }); </script>La URL BusquedaDeProvinciasPorPais recibirá el parámetro val, con el cual podrá generar el resultado apropiado para llenar el combo de Provincias.
El ejemplo de Ubicación Geográfica
Pero más facil que decir es hacer, así que veamos la resolución del ejemplo de "Países - Provincias - Ciudades". Para esta solución usaremos tres archivos:
- demo.html, que será la página HTML que contiene el código del formulario.
- datos-provincias.js, que será la URL que devolverá los datos de las provincias.
- datos-ciudades.js, que será la URL que devolverá los datos de las ciudades.
En una implementación "real", las URL de datos-provincias.js y datos-ciudades.js serían páginas dinámicas que generarían el contenido de acuerdo al valor seleccionado por el usuario.
Pueden descargar los siguientes archivos para probarlo localmente en sus máquinas (recomendado).
La página HTML
<html> <head> <script type="text/javascript" src="jquery/jquery.js"></script> <script type="text/javascript" src="jquery/jquery.cascade.js"></script> <script type="text/javascript" src="jquery/jquery.cascade.ext.js"></script> <script type="text/javascript" src="jquery/jquery.templating.js"></script> <script type="text/javascript"> function commonTemplate(item) { return "<option value='" + item.Value + "'>" + item.Text + "</option>"; }; function commonTemplate2(item) { return "<option value='" + item.Value + "'>***" + item.Text + "***</option>"; }; function commonMatch(selectedValue) { return this.When == selectedValue; }; </script> </head> <body> <h1>Ubicacion</h1> <div> <label>Pais <select id="pais"> <option value="AR">Argentina</option> <option value="ES">España</option> <option value="MX">Mexico</option> </select> </label> <label>Provincia <select id="provincia"></select> </label> <label>Ciudad <select id="ciudad"></select> </label> </div> <script type="text/javascript"> $(document).ready(function() { $("#provincia").cascade("#pais",{ ajax: {url: 'datos-provincias.js'}, template: commonTemplate, match: commonMatch }); $("#ciudad").cascade("#provincia",{ ajax: {url: 'datos-ciudades.js'}, template: commonTemplate, match: commonMatch }); //forzamos un evento de cambio para que se carge por primera vez $("#pais").change(); }); </script> </body> </html>
datos-provincias.js
[ {'When':'AR','Value':'AR-1','Text':'Buenos Aires'}, {'When':'AR','Value':'AR-2','Text':'Neuquen'}, {'When':'ES','Value':'ES-1','Text':'Barcelona'}, {'When':'ES','Value':'ES-2','Text':'Lugo'}, {'When':'MX','Value':'MX-1','Text':'Chiapas'}, {'When':'MX','Value':'MX-2','Text':'Durango'}, ]
datos-ciudades.js
[ {'When':'AR-1','Value':'AR-1-1','Text':'La Plata'}, {'When':'AR-1','Value':'AR-1-2','Text':'Tandil'}, {'When':'AR-2','Value':'AR-2-1','Text':'San Martin de los Andes'}, {'When':'AR-2','Value':'AR-2-2','Text':'Villa La Angostura'}, {'When':'ES-1','Value':'ES-1-1','Text':'Badalona'}, {'When':'ES-1','Value':'ES-1-2','Text':'Sant Andreu de la Barca'}, {'When':'ES-2','Value':'ES-2-1','Text':'Monterroso'}, {'When':'ES-2','Value':'ES-2-2','Text':'Baralla'}, {'When':'MX-1','Value':'MX-1-1','Text':'San Cristobal de Las Casas'}, {'When':'MX-1','Value':'MX-1-2','Text':'Palenque'}, {'When':'MX-2','Value':'MX-2-2','Text':'Bermejillo'}, {'When':'MX-2','Value':'MX-2-2','Text':'Ceballos'}, ]
Y eso es todo. Como vemos, los archivos tienen todos los datos necesarios para mostrar los detalles. En una implementación con páginas dinámicas, sólo sería necesario generar los datos para el elemento seleccionado.
Descargar el ejemplo
Lo mejor es verlo funcionando, así que les recomiendo descargar el ejemplo completo de JQuery Cascade (que incluye estos archivos y las librerías JavaScript necesarias) para ver a JQuery Cascade en acción. Simplemente descompriman el archivo y, con su navegador favorito, abran el archivo demo.html
Por otro lado, la página de JQuery Cascade tiene una demostración muy completa con las distintas alternativas de uso de esta librería.
-
Invitado
Permalinkquiero hacer lo que dices
En una implementación \"real\", las URL de datos-provincias.js y datos-ciudades.js serían páginas dinámicas que generarían el contenido de acuerdo al valor seleccionado por el usuario.
pero o se como quitar los .js y poner los datos.
Si me puedes ayudar. como inserto esos datos dentro del html sin el javascript
Gracias -
Vas a tener que generar dinámicamente el contenido. Fijate que en el atributo \"ajax\" del cascade de pais y provincia se apunta a la URL que devuelve el listado correspondiente. En vez de apuntar a un recurso \"estático\" tenés que apuntar a un recurso dinámico (por ejemplo, \"datos-provincias.php\") que genere la información necesaria. En este caso, te va a llegar el parámetro \"val\" el cual tiene el valor del combo anterior seleccionado, para que puedas filtrar acorde.
-
Invitado
PermalinkY hay alguna forma de que en vez de estar en una pagina aparte este en la misma??,
Me explico lo que quiero es poner ese codigo mismo el de datos-provincias pero en vez de en un js externo en uno dentro del propio codigo javascript dentro de la pagina HTML.
Programo en un lenguaje que se llama webfocus y con solo poner una sentencia y llamando al html me incluye ya el codigo.
Seria en vez de dinamico como si fuera fijo.
No se si me explico bien -
Si, es posible eso que querés también. En vez de usar el atributo "ajax", hay que usar el atributo "list", y le pasas una variable que contenga el array con todos los datos.
En la demostracion de Jquery Cascade ([url]http://dev.chayachronicles.com/jquery/cascade/index.html[/url]) el primer ejemplo hace exactamente eso (fijate el codigo fuente de la página para el uso completo). Queda algo como esto:
//la variable con la lista de elementos
var list1 = [
{\'When\':\'A\',\'Value\':\'A1\',\'Text\':\'A1\'},
{\'When\':\'D\',\'Value\':\'D2\',\'Text\':\'D2\'}
];
//se usa el atributo "list" para referenciar a la variable
jQuery(document).ready(function()
{
jQuery(\'#simple_child\').cascade(\'#simple\',{
list: list1,
template: commonTemplate,
match: commonMatch
});
}); -
Invitado
PermalinkMuchisimas Gracias.
Me has ayudado mucho.
Estoy empezando ahora con jquery y me parece un gran invento.
Podrias recomendarme algun Tutorial?? -
Invitado
PermalinkLeito tengo otra preguntilla. eske llevo toda la mñn intentando hacer una cosa.
imaginate que tengo dos repetidos, me explico:
el A1 pertenece a A y a B
{\'When\':\'A\',\'Value\':\'A1\',\'Text\':\'A1\'},
{\'When\':\'B\',\'Value\':\'A1\',\'Text\':\'A1\'}
La putada es que me sale repetido.
Creo que con esta forma de listas no se puede hacer.
Sabes de combos dependiente y que salgar sin repetir pero que un hijo tenga varios padres?? -
En castellano no conozco ninguno (aunque podría ser una buena idea para la sección de Cursos...) Por otro lado, a mi me ayudó mucho la guía de inicio de JQuery ([url]http://docs.jquery.com/Tutorials:Getting_Started_with_jQuery[/url])
-
Invitado
PermalinkHola, gente... alguno sabe como hacer esto pero tomar los datos de una base mysql?
Saludos
Alejandro -
Invitado
PermalinkBuenas tardes, al poner en ajax: 'datos-provincias.js' no me carga los datos, sin embargo si lo pongo como una lista estática si me los coge...Me gustaría saber si puedo poner en ajax: un método javascript de la misma página y como se pondría. Saludos y gracias
-
Invitado
PermalinkPerfecto el script, me ha venido de perlas!.
Sólo una duda, ¿cómo se podría añadir un gif loading, mientras carga las ciudades?, ya que al añadir las localidades de españa, la lista se alarga y tarda un poco en cargar, sería estupendo poder ponerle un loading mediante un gif animado a la derecha del select. -
Invitado
Permalinkcomo puedo hacer, yo en una base de dato tengo tres tablas (provincias-departamentos-localidades)para usar este ejemplo.. o que tengo que modificar para agregar las provincias que faltan y sus localidades....
-
Invitado
Permalinklo estoy implementando para un combo q hace consulta a base de datos, pero no se si todos los tengo q cargar en el oredy y mas q nada , y como puedo implementa un getJON dentro del mismo?¿ , se puede o no?¿
-
-
Invitado
PermalinkTengo problemas cuando ejecuto este ejemplo en mi servidor (Red Hat).
Alguien sabe a que se debe? -
Invitado
PermalinkHola, exelente artículo, los felicito, me ha ayudado mucho.
Pero necesito inicializar los combos con datos que están en la base de datos.
Por ejemplo:
Valor inicial del combo uno:
ES --este es fácil xq no tiene que ver con jquery
Valor del combo dos
ES-2 -- no se como ponerle selected a este
Valor del combo tres
ES-2-2 -- y menos a este.
Me prodrían ayudar ??? gracias -
Invitado
PermalinkEste plugin no funciona con la version 1.4 alguien sabe que otro plugin o alguna otra manera de hacer esto.
gracias -
Invitado
PermalinkYo tb he tenido el mismo problema y he probado esto y me funciona.
function commonTemplate(item) {
return "" + item.Text + "";
};
function commonMatch(selectedValue) {
return this.When == selectedValue;
};
var list1 = [
{'When':'AR','Value':'AR-1','Text':'Buenos Aires','TheSelected':''},
{'When':'AR','Value':'AR-2','Text':'Neuquen','TheSelected':''},
{'When':'ES','Value':'ES-1','Text':'Barcelona','TheSelected':''},
{'When':'ES','Value':'ES-2','Text':'Lugo','TheSelected':''},
{'When':'ES','Value':'ES-3','Text':'Sevilla','TheSelected':'selected'},
{'When':'ES','Value':'ES-4','Text':'malaga','TheSelected':''},
{'When':'MX','Value':'MX-1','Text':'Chiapas','TheSelected':''},
{'When':'MX','Value':'MX-2','Text':'Durango','TheSelected':''},
]; -
Invitado
PermalinkNo se porq razon se ha copiado mal. Lo vuelvo a pegar :
function commonTemplate(item) {
return "" + item.Text + "";
};
function commonMatch(selectedValue) {
return this.When == selectedValue;
};
var list1 = [
{'When':'AR','Value':'AR-1','Text':'Buenos Aires','TheSelected':''},
{'When':'AR','Value':'AR-2','Text':'Neuquen','TheSelected':''},
{'When':'ES','Value':'ES-1','Text':'Barcelona','TheSelected':''},
{'When':'ES','Value':'ES-2','Text':'Lugo','TheSelected':''},
{'When':'ES','Value':'ES-3','Text':'Sevilla','TheSelected':'selected'},
{'When':'ES','Value':'ES-4','Text':'malaga','TheSelected':''},
{'When':'MX','Value':'MX-1','Text':'Chiapas','TheSelected':''},
{'When':'MX','Value':'MX-2','Text':'Durango','TheSelected':''},
]; -
Invitado
Permalinkfunction commonTemplate(item) {
return " < option value='" + item.Value + "' " + item.TheSelected + " > " + item.Text + " < /option > ";
};
function commonMatch(selectedValue) {
return this.When == selectedValue;
};
var list1 = [
{'When':'AR','Value':'AR-1','Text':'Buenos Aires','TheSelected':''},
{'When':'AR','Value':'AR-2','Text':'Neuquen','TheSelected':''},
{'When':'ES','Value':'ES-1','Text':'Barcelona','TheSelected':''},
{'When':'ES','Value':'ES-2','Text':'Lugo','TheSelected':''},
{'When':'ES','Value':'ES-3','Text':'Sevilla','TheSelected':'selected'},
{'When':'ES','Value':'ES-4','Text':'malaga','TheSelected':''},
{'When':'MX','Value':'MX-1','Text':'Chiapas','TheSelected':''},
{'When':'MX','Value':'MX-2','Text':'Durango','TheSelected':''},
]; -
Invitado
PermalinkEsta ultima si se ha copiado bien. Espero que te sirva. No olvides de quitar los espacios antes y despues de lo que he puesto para que se copie bien. Un saludo

Comentarios (30)