viernes, 22 de junio de 2012

Actualizar elemento HTML ubicado fuera de un UpdatePanel

Esta funcionalidad es de gran importancia para aquellas personas que utilizan el Control UpdatePanel de ASP.NET y en ocasiones requieren ubicar controles ASP como Label, Button, TextBox o controles HTML como Input, Span, entre otros, por fuera del control UpdatePanel (ilustrado en la figura 1.).

Codigo ASP.NET
Figura 1.

El problema consiste en que al momento de querer cambiar propiedades de los controles que están por fuera el UpdatePanel, estos no se verán reflejados debido a que solo se actualizarán los elementos que están dentro del Panel. Para ver un ejemplo mas claro, supongamos que al presionar el botón Submit se quiere bloquear el botón Hab/deshab o un TextBox (fuera del UpdatePanel) desde el CodeBehind por alguna condición dada.

    protected void Button1_Click(object sender, EventArgs e)
    {
        if (Button2.Enabled) {
            Label1.Text = DateTime.Now.ToString();
            Button2.Enabled = false;
        }
        else {
            Label1.Text = "Fecha inactiva";
            Button2.Enabled = true;
        }
    }

Pero dado que el elemento Label1Button2 se encuentra fuera del Panel, se cambiará su propiedad Enable (dentro del servidor), pero este cambio no se verá reflejado en el explorador debido a que el cliente solo recibe actualización de elementos contenidos dentro el UpdatePanel, como función de AJAX.


La solución está en que debemos cambiar el código anterior por el siguiente:


    protected void Button1_Click(object sender, EventArgs e)
    {
        if (Button2.Enabled) {
            ScriptManager1.RegisterDataItem(Label1, DateTime.Now.ToString());
            ScriptManager1.RegisterDataItem(Button2, "false");
        }
        else {
            ScriptManager1.RegisterDataItem(Label1, "Fecha inactiva");
            ScriptManager1.RegisterDataItem(Button2, "true");
        }
    }

El método RegisterDataItem() del ScriptManager envía datos en una llamada asíncrona (desde UpdatePanel) a los controles que se encuentran fuera del UpdatePanel. Además se debe manejar el siguiente evento en el cliente.
Nota: Este código debe colocarse después de la definición del control ScriptManager, de lo contrario dará un error diciendo que el espacio de nombres Sys no está definido aún.

    <script type="text/javascript" language="javascript">

        Sys.WebForms.PageRequestManager.getInstance().add_pageLoading(
            PageLoadingHandler);

         function  PageLoadingHandler(sender, args)
        {
             var dataItems = args.get_dataItems();

             if  ($get('Label1') !==  null)
                $get('Label1').innerHTML = dataItems['Label1'];
             if  ($get('Button2') !==  null)
                 if  (dataItems['Button2'] == "true")
                    $('input#Button2').attr('disabled', dataItems['Button2']);
                else
                    $('input#Button2').removeAttr('disabled');
            
        }
     </script>

En primer lugar se obtiene una instancia de la clase Sys.WebFroms.PageRequestManager que es la encargada de actualizar los controles que se encuentran dentro del UpdatePanel. Antes de que esta actualización ocurra, gestionamos el evento pageLoading() y recogemos los datos enviados desde el servidor para actualizar el Label1Button2.

De esta forma se ha creado un manejador del evento propio, RecogerDatosHandler(), que por medio de la colección args podemos acceder a los datos enviados desde el servidor.

No olvide importar el js con las librerias de JQuery para manejo JavaScript de los elementos en el cliente.
<script src="../js/jquery-1.4.2.min.js" type="text/javascript"></script>


Para hacer este Post tomé de ayuda el siguiente Blog: http://oscarsotorrio.com/post/2009/12/08/Enviar-datos-asincronos-a-un-control-fuera-de-un-UpdatePanel.aspx



5 comentarios:

  1. y como hago para que mi mi lebel sea visible=true si el label esta fuera del updatepanel y mi boton dentro del updatepanel

    ResponderEliminar
    Respuestas
    1. Saludos,
      Para ese caso debes hacer lo siguiente:
      En el codigo C# debes enviar:
      ScriptManager1.RegisterDataItem(Label1, "none");

      y en el codigo de aspx, dentro de la funcion JavaScript PageLoadingHandler, debes colocar:
      en lugar de: $get('Label1').innerHTML = dataItems['Label1'];

      Pones: $get('Label1').css("display", dataItems['Label1']);

      Esto sería manejo de Style a un elemento HTML por medio de JQuery
      Espero esto le sirva de ayuda.

      Eliminar
    2. Genial, lo he montado y funciona con un pero. Estoy actualizando el contenido de un DIV y el nuevo html que pongo dentro del DIV usa estilos de la página pero no se aplican.
      El código HTML resultante es correcto pero se visualiza mal. No sé cuál puede ser el problema.

      Eliminar
    3. EDITO: Este problema me ocurre en Internet Explorer (funciona bien en Firefox y Chrome)

      Eliminar
  2. in this link you will find an example, I've tested and works correctly, I hope they serve:

    http://www.systemdeveloper.info/2014/02/how-do-i-add-javascript-updatepanel-in.html

    They can also look at this other link,

    http://www.systemdeveloper.info/2014/01/fileupload-control-in-update-panel.html

    ResponderEliminar