Contenido

Combos dependientes y el desarrollo web que hay hoy en día.

19 Ene

+ 18

Hace unos días tuve que acercarme, por motivos laborales, a otra empresa para solucionar, o dar solución, sobre un problema Javascript sobre una página que nos estaban haciendo. Al revisar el código que estaban haciendo descubrí el problema y me horrorizé al ver el planteamiento que habían elegido para llevar a cabo dicha tarea.

Pongamos en situación

Imaginemos que queremos hacer una aplicación en la que necesitamos disponer de una serie de combos dependientes, por ejemplo pais/destino. Imaginemos que queremos usar ajax para recargar el combo de destinos al seleccionar un pais. Imaginemos que no tenemos mucha idea y decidimos hacer uso de un setInterval() para controlar el momento en el que el combo cambie…

Veamos el código

var pais = document.getElementByID("pais");
vat tmpPais = "";

function actualizaDestinos() {
	// Ajax...
	 	....
}

function compruebaPais(){
	if (tmpPais != pais.value) actualizaDestinos();
	else tmpPais = pais.value;
}

setInterval("compruebaPais", 1000);

Como podemos ver, el planteamiento es el siguiente, una especie de comprobación redundante como esta:

- ¿Estás modificado?
- No
- ¿Estás modificado?
- Si
- Entonces, alla voy!!!

Evidentemente, este sistema no es el más correcto, ya que por una petición satisfactoria se han producido N insatisfactorias. Lo que se puede evitar con un simple cambio de concepto.

Un planteamiento más correcto

Al intentar explicarles, que el uso de Ajax, suele ir ligado a la interacción por parte del usuario creo que les hize comprender que estaban enfocando el problema erroneamente. ¿Por que preguntar cada segundo si algo se ha cambiado, cuando puedes hacer que te avisen cuando algo cambie?

Gracias a métodos como el de onchange, podemos hacer que sea el combo el que nos avise de que hemos realizado el cambio y en ese momento lanzar la petición y cargar el combo correspondiente en el momento adecuado.

Veamos el código

var pais = document.getElementByID("pais");
vat tmpPais = "";

function actualizaDestinos() {
	// Ajax...
	 	....
}

function compruebaPais(){
	if (tmpPais != pais.value) actualizaDestinos();
	else tmpPais = pais.value;
}

pais.addEventListener("change", compruebaPais, false);
//pais.onchange = compruebaPais; (machacando el evento)

Como podemos ver, la cosa cambia. La conversación entre los combos es muy diferente y casi nula. Esto es debido a que el planteamiento lógico, conociendo los métodos disponibles nos puede facilitar la tarea.

- Estoy esperando, ya me avisarás.
- ...
- He cambiado, haz lo que te de la gana :D
- Me pongo manos a la obra, gracias.
 

Evidentemente esta solución evita, además de peticiones constantes, una serie de problemas añadidos al interval, que si no es tratado debidamente, aúnque este cambie los combos de la forma correcta, seguriá lanzando la petición indefinidamente hasta que cambiemos de página.

Conclusión

Con este ejemplo, no quiero decir que sea incorrecto el primer método, por que lamentablemente todo esto funciona y los clientes inexpertos ven una aplicación que funciona y que cubre la idea que ellos tenían, por lo tanto mirando desde el punto de vista del cliente, nunca puede ser erroneo algo que cumple lo que ellos quieren. Solo intento explicar que es necesario formarnos y estar al tanto de novedades relacionadas con el lenguaje que usamos, para realizar una tarea más profesional.

Con respecto al ejemplo número 2, hay que decir que este sistema no es nada accesible y que un usuario sin javascript se dará la vuelta y no volverá a nuestra página, por eso debemos pensar en todo y planear la forma de atacar el problema con todas las herramientas de las que disponemos. Sinó fuera así aún estaríamos usando iframes para cargar porciones de páginas. ¿no creeis?

  • Toda la razon
    Aparte, La explicacion es excelente =)
    Saludos!

  • Más facil aun:
    Se puede llamar a la funcion con un simple onchange=»actualizarDestino(this)» en select directamente.
    Pero claro, los Event Listeners son más hippies 🙂

    PD: En el comentario anterior lo puse con codigo, pero se lo comio el sanitizer

  • Muy clarificador; pero el «haya voy» casi me mata…

    Sin acritud, saludos!

  • Por cierto, el ejemplo es prácticamente el mismo que usaron en Fundamentos de Ordenadores para explicarnos por qué la espera activa no es una buena idea xD

  • Correctísimo el artículo, pero también hay que mencionar que para cuestiones de javascript _ y más específicamente en la implementación de características AJAX_ existen frameworks (livianos) que facilitan la construcción de peticiones asíncronas y el manejo del DOM.

    Yo he experimentado con algunos y me he quedado con Prototype (http://prototypejs.org) aunque también jQuery tiene muchos adeptos.

    Saludos

  • ¿Y por qué vas hacia el haya? 😛

  • Si supierais lo que hay por ahí en webs de grandes empresas… y es que tienen contratado a personal incompetente.

  • Hombre no es por ser mamoncete, pero esa gente parece que no tienen mucha idea de programacion, el polling solo se debe usar si no hay mas remedio y no hay ninguna manera de recibir un evento que nos diga cuando debemos empezar a ejecutar una parte del codigo.

    Pienso que hay mucha gente que se pone a programar y no tiene ciertas nociones basicas de programacion.

    Pd:Que algo funcione ahora no significa que funcionara en el futuro

    1Saludo

  • Andrés

    Hace poco me tocó implementar en un formulario de un proyecto del trabajo un combo dependiente para que el usuario seleccione País y luego Provincia.

    Lo implementé finalmente con javascript pero se me presentó la duda de cómo hacerlo cuando javascript no está disponible del lado del cliente. Se me ocurrieron 2 formas de hacerlo pero no se cuál era mejor:

    1. Que el combo país y provincia estuvieran siempre presentes, pero el de provincias contenía algo así como: «Provincia (País)».

    2. Otra forma era que el usuario tuviera que enviar el formulario al seleccionar país con un botón específico para que luego apareciera el combo de provincias ya filtrado.

    Utilicé la primera altenativa, pero me quedó la inquietud.

    ¿Cuál piensas tu que es la forma más correcta, alguna alternativa?

  • Yo hacía esto antes del Ajax con Remote Scriptintg. http://www.ashleyit.com/rs/jsrs/select/php/select.php
    Ahora hago lo mismo con Prototype pero con 300 lineas de código menos, jeje. Que lindo que es el avance.

  • Por los comentarios hasta ahora se ve claro que todos dominan la parte javascript del asunto. Pero… están los demás como yo? que pasa con la accesibilidad? llevo un rato buscando y aun no vi ninguna solución facil/cómoda de integrar.

    En mi caso intento crear un formulario de compra con verificación de datos y accesible. Hasta ahora todo bien con jquery pero la parte accesible de una selección pais->provincia (cuestiones de gastos de envío) me está matando.

    ¿Alternativas?

  • lamento el comentario duplicado.
    Lo mejor que encontré hasta ahora fue:

    http://es.groups.yahoo.com/group/accesoweb/message/11594

  • @oldlastman: Para conseguir hacerlo accesible tendrías que plantearlo de otra manera. A ver si esta idea te sirve:

    1) Debemos pensar en 2 (o el número de combos) formularios diferentes. Con sus botones de submit.

    2) Imaginemos el primer combo (Pais), lo cargamos con la lista de paises y únicamente mostramos dicho combo. Junto a su botón de submit que hará que cargues el fichero con el combo (Destinos) con los datos del Pais correspondiente.

    De esta forma tenemos la parte sin Javascript, hemos usado el antiguo método de 2 pasos en lugar de 1. Y ahora con javascript miramos de mejorar esa experiencia.

    Aqui es donde está la gracia, por que podríamos hacer uso de javascript para ocultar los botones de submit y crear el combo con las opciones necesarias lanzando peticiones al servidor para cargar ese combo recien creado.

    De esta forma, los usuarios con Javascript, lo harán con 1 solo paso, los usuarios sin Javascript tendrán que hacerlo en 2.

    Espero que haya quedado clara la idea. Hay otras formas de hacerlo, pero creo que esta es la más correcta. Quizas tenga que hacer un post tutorial sobre el tema.

    Saludos

  • Buenas… he estado buscando algo que me ayude a resolver cómo insertar un nuevo registro en la base de datos y que este nuevo dato aparezca en un combo, es decir, tengo un combo con materiales, este depende a su vez de un combo de tipo de materiales, ya hice la inserción de los materiales seleccionando la opción «nuevo» en el combo materiales, usando una ventana emergente, pero no he podido lograr que el material recien insertado aparezca en el combo, no puedo usar un submit sobre esta ventana porque perdería todo un código javascript que ya está hecho.
    Alguien puede ayudarme con esto???
    Gracias

Comentar

#

Me reservo el derecho de eliminar y/o modificar los comentarios que contengan lenguaje inapropiado, spam u otras conductas no apropiadas en una comunidad civilizada. Si tu comentario no aparece, puede ser que akismet lo haya capturado, cada día lo reviso y lo coloco en su lugar. Siento las molestias.