miércoles, junio 27, 2007

Ajax en ASP (sin ASP.net)

Leí ayer en un blog (http://warneronstine.com/blog) una buena idea: escribir siempre en el blog los problemas encontrados y las lecciones aprendidas en el desarrollo de un proyecto. Acabo de terminar un proyecto y tengo varias cosas en la mente, así que ahí van.

Este es un proyecto en ASP, era la modificación a un sitio existente, de modo que migrarlo a ASP.net o algo aún mejor no era una opción. El problema es sencillo de enunciar: para subir cierto contenido, existen actualmente unas determinadas categorías, lo que quería el usuario era tener subcategorías (sólo un nivel) y que ahora el contenido se subiera a ellas. Sencillo, típico. Latoso, también, por la plataforma, y por tener que hacer las consabidas pantallitas de alta, baja, modificación de subcategorías, etc.

De modo que, intentando divertirme mientras lo hacía, busqué algún widget que me dejara hacer todo eso pero con Ajax. Al principio no fue fácil encontrar algo que fuera puramente para ASP, pero me topé con un artículo y una demo que me hicieron las cosas fáciles: http://aspwebsolution.com/articles/xmlrep/ajax_treeview1/index.htm. Es un "tree view" que carga las "ramas" vía Ajax, y me pareció atractivo por varias razones:
  • La pantalla existente traía la lista de categorías de la base de datos, de modo que no tendría que cambiar el query inicial
  • Para cada "rama", sólo habíra que modificar el query que se hacía vía Ajax, de modo que la nueva funcionalidad entraría más o menos fácilmente, el famoso unobtrusive que tanto hay que perseguir, según nos dicen los gurús.
  • De otro modo, si hubiera querido pintar de un sólo jalón tanto categorías como subcategorías, el query habría estado complejo, al menos con los cambios que planeé a la base de datos.
Y por cierto, estos cambios eran sólo agregar una columna a la tabla de categorias, id_padre, que apuntaría obviamente al ID del padre del nodo en cuestión, y que tendría un valor de cero cuando el nodo fuera nodo raíz.

Realmente fue sencillo adaptar el arbolito para que desplegara categorías y subcategorías, quedando de esta forma:



Pero todavía hacía falta el CRUD, o en español, el ABC para las categorías. Es decir, permitir que se modificara el nombre de una categoría o subcategoría, borrar, agregar, etc. Decidí utilizar también Ajax para esto, intentando adaptar el script para el arbolito. Mi idea era que cuando alguien seleccionara "agregar subcategoría" apareciera una cajita de texto en la que se pudiera capturar el nombre, se le diera "Enviar", y el arbolito se actualizara automáticamente, todo sin cambiar de página.

Bueno, esto fue lo interesante, en realidad. El autor del código del arbolito había hecho algunas cosas muy lindas y genéricas, pero no estaba pensado para hacer cajitas voladoras ni actualizaciones mágicas. La solución original del treeview era como sigue:

  • La página principal crea el árbol vía javascript puro, y utiliza un div para señalizar el lugar donde se dibujará.
  • Todo el javascript está en el archivo scripts.js, que a su vez llama a ajax.js. Este último tiene el código consabido del XMLHttpRequest, pero está amarrado para que siempre, al llegar la respuesta, sea llamada la función processReqChange(). Me dije "aquí es donde voy a tener que poner mis ifs", pero me esperaba una sorpresa:
  • El autor tuvo el buen gusto de devolver todo el procesamiento en un XML, y después aplicarle un XSL para darle formato. Esto hizo maravillas para la sacrosanta Separación de Código: los archivos que modifican base de datos quedaron por un lado, el "controlador" del flujo en otro, y el archivo que controla el desplegado en un XSL. Por fortuna, mi mamá ya me había dicho que saber XSL me iba a llevar lejos, así que no fue un problema.
  • Y algo mejor: el XML que devuelve el "modelo" tiene dos partes principales:

    1 <response>
    2 <method>getUpdateResponse</method>
    3 <result>1</result>
    4 </response>

    La segunda parte, result, trae el resultado de la operación, y ahí es donde está el XML que es convertido desde el XSL; la primera parte, method, es la que me pareció muy ingeniosa: trae el nombre del método con el que debe procesarse el resultado. Esto me hizo un click inmediato: ¡sólo cambiando el nombre del método podría hacer que el mini-framework sirviera para hacer nuevos trucos!
De modo que mi solución fue simplemente poner los consabidos ifs en las partes del código que mandaban llamar al generador de XML, que cada uno de ellos devolviera el nombre del método que debía procesar la respuesta, y agregar ifs adicionales en el método que procesa las respuestas vía Ajax. De modo que el código asp que hace inserciones en la base de datos quedó como sigue:

1 <response>
2 <method>getUpdateResponse</method>
3 <result><% Call insert(id, value) %></result>
4 </response>

...y algo similar hice para el borrado y modificado de categorías (la función insert(id, value) simplemente ejecuta un insert en la base de datos). Por supuesto, la función insert devuelve un 1 cuando la operación fue exitosa y el número de error cuando no. En el caso de las funciones que necesito que generen HTML, devuelvo directamente el XML con el resultado.

El resto del trabajo fue simplemente agregar un poco de javascript para aparecer y desaparecer layers, y lograr el cómodo efecto de no tener que refrescar la página para tareas tan simples como agregar una rama o modificar su nombre:



El último detalle digno de mencionarse de cómo quedó la solución es que me pidieron que las categorías principales no pudieran tener contenido, sólo las ramas. Inicialmente pensé que esto tendría que lograrlo con alguna serie de validaciones, sin embargo simplemente quité en el XSL la liga que se mostraba en categorías "raíz", y ya: sólo las subcategorías tienen ahora link hacia la página de detalle. Claro, un usuario listillo podría ver que estoy enviando el ID de la categoría y cambiarla en el URL, pero estamos hablando de un sistema que da servicio sólo a dos usuarios, de modo que no me preocupa.

No hay comentarios.:

Publicar un comentario

Venga, sé que algo opinas