jQuery, UpdatePanel y Postbacks

.Net, jQuery Sin comentarios »

Esto de jQuery se esta convirtiendo en un vicio (compite mano a mano con Silverlight) y conforme más juegas más quieres y más te diviertes. Y si añadimos UpdatePanels, nos divertimos aún más si cabe.

Al usar jQuery, seguramente usaremos el evento Ready para añadir manejadores de eventos, añadir efectos, añadir / quitar clases.... en fin, inicializar los controles de nuestra página.  El evento Ready de jQuery  es un evento que se lanza una vez que todo el DOM de la página ha sido cargado por completo. Por otro lado tenemos los postback parciales provocados por los updatePanels. El cometido de estos controles es evitar la carga completa de la página, es decir, solo actualizar aquellos controles contenidos en el control UpdatePanel. Pero lo que hace realmente no es actualizar los valores de los controles, sino que los sustituye  por otros nuevos, tras lo cual todos los controles que hay en el UpdatePanel perderán las clases y eventos asociados a ellos en la inicialización de la página. Esto incluye tanto controles de servidor como controles de cliente, todos serán reemplazados.

Por ejemplo tomemos como ejemplo este UpdatePanel y controles:

Â

HTML:
  1. <asp:UpdatePanel ID="UP" runat="server">
  2.         <ContentTemplate>
  3.             <table>
  4.                 <tr>
  5.                     <td width="40px">
  6.                         <span class="label8">Nombre: </span>
  7.                     </td>
  8.                     <td width="40px">
  9.                         <input type="text" id="txtnombre" class="inputText" />
  10.                     </td>
  11.                     <td width="80px">
  12.                         <asp:TextBox runat="server" ID="lblNombre"/>
  13.                     </td>
  14.                 </tr>
  15.                 <tr>
  16.                     <td>
  17.                         <span class="label8">Direccion: </span>
  18.                     </td>
  19.                     <td>
  20.                         <input type="text" id="txtDireccion" class="inputText" />
  21.                     </td>
  22.                     <td>
  23.                         <asp:TextBox runat="server" ID="lblDireccion"/>
  24.                     </td>
  25.                 </tr>
  26.                 <tr>
  27.                     <td>
  28.                         <asp:Button runat="server" ID="btnAceptar" Text="Aceptar"
  29.                             CssClass="btnMandatory" onclick="btnAceptar_Click"/>
  30.                     </td>
  31.                 </tr>
  32.             </table>
  33.         </ContentTemplate>
  34.    </asp:UpdatePanel>

 La inicialización de la página la llevaríamos a cabo normalmente así:

JavaScript:
  1.        $(document).ready(function () {
  2.             // Inicializacion de controles
  3.  
  4.        });

De esta manerá todo funciona correctamente, pero solo mientras no pulsemos el botón "Aceptar" que provoca el postpack parcial. Una vez hagamos click, todos los eventos asociados a los controles desaparecerán. Para solucionarlo tenemos que reasignarlos nuevamente, y una forma de hacerlo es añadiendo un manejador al evento que controla cuando un postback asíncrono ha finalizado. Nuestro código podría quedar así:

JavaScript:
  1. Sys.WebForms.PageRequestManager.getInstance().add_endRequest(Load);
  2.  
  3.         $(document).ready(function () {
  4.             Load();
  5.         });
  6.  
  7.         function Load() {
  8.             $('#' + '<%=btnAceptar.ClientID %>').attr('disabled', true);
  9.             $('#' + '<%=lblNombre.ClientID %>').attr('readonly', true);
  10.             $('#' + '<%=lblDireccion.ClientID %>').attr('readonly', true);
  11.  
  12.             $(".inputText").blur(function () {
  13.                 $(this).css("background-color", "FFFFFF");
  14.             });
  15.  
  16.             $(".inputText").focus(function () {
  17.                 $(this).css("background-color", "CCCCCC");
  18.             });
  19.  
  20.             $(".inputText").keyup(function () {
  21.  
  22.  
  23.                 if ($(this).val() == '')
  24.                     $('#' + '<%=btnAceptar.ClientID %>').attr('disabled', true);
  25.                 else {
  26.                     var nodata = false;
  27.                     $.each($(".inputText"), function () {
  28.                         if ($(this).val() == '')
  29.                             nodata = true;
  30.                     });
  31.                     $('#' + '<%=btnAceptar.ClientID %>').attr('disabled', nodata);
  32.                 }
  33.  
  34.             });
  35.  
  36.             $('#' + '<%=btnAceptar.ClientID %>').click(function () {
  37.                 $('#' + '<%=lblNombre.ClientID %>').attr('value', $("#txtnombre").val());
  38.                 $('#' + '<%=lblDireccion.ClientID %>').attr('value', $("#txtDireccion").val());               
  39.             });
  40.         } 

Lo que hemos hecho es envolver todo el código que teníamos en el evento Ready de jQuery en una función, y llamar a esta función tanto en el evento Ready, como cuando el postback asincrono del updatePanel ha terminado.

Una segunda opción sería Inyectar un script desde servidor que invoque a esta nueva función.

C#:
  1. protected void btnAceptar_Click(object sender, EventArgs e)
  2.  {
  3.         lblNombre.Text = lblNombre.Text + "--&gt; Validado con Exito";
  4.         lblDireccion.Text = lblDireccion.Text + "--&gt; Validado con Exito";
  5.         ScriptManager.RegisterStartupScript(this, GetType(), "", "Load();", true);
  6.  }

jQuery o Ajax Control Toolkit

.Net, Web Sin comentarios »

A día de hoy yo no tendría duda sobre cual opción elegir, opción que no tiene que ser mejor que la otra. Realmente, yo enfocaría el dilema mas bien desde el punto de vista de aplicación web AJAX (orientada al servicio), o aplicación web convencional (.net por supuesto), con sus postbacks (o callbacks) y sus Update Panels. (Debería de estar penalizado el uso del control Update Panel :-) )

Ajax Control Toolkit

Esta opción nos deja en el ámbito de una aplicación web .Net tradicional con controles de servidor, por lo que seguramente tendremos el grueso de la aplicación en el servidor. Con esto no quiero decir que no sea posible tener lógica en cliente, pero si que resulta bastante engorroso trabajar con los controles del ajax control tolkit con javascript. Por otro lado no debemos olvidar que son controles de servidor, y que son muy fáciles de usar, pero que cuando se complica el desarrollo y la web,  no se por qué, pero el trabajo se complica.  Otro punto es el peso de las librerías, puf, te echan para atrás. Y un punto no menos importante, si por ejemplo tenemos que hacer una modificación de un Extender, digamos por ejemplo el AutoCcomplete, tendremos que generar un nuevo build y añadir la nueva referencia, y rezar por tener problemas de versiones a la hora de realizar el deploy en el servidor. A modo de anectdota, mencionar que un proyecto en el que estuve trabajando, en cual teniamos un Auto Complete Extender customizado,  tuvimos problemas de referencias cruzadas entre versiones de librerias,  y  con el timestamp del build generado del Extender con la fecha del servidor. Hora del Build X , hora del Servidor de despliegue X-6. Solución, cambiar la hora a la maquina de build y realizar un nuevo build con un timestamp de fecha menor que la hora del servidor web. 

Leer el artículo completo »

WP Theme & Icons by N.Design Studio
Entries RSS Comments RSS Log in

Switch to our mobile site