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.