Volver a vincular eventos en jQuery después de la actualización de Ajax (panel de actualización)

80

Tengo varios elementos de entrada y opción en mi página, cada uno (bueno, casi) tiene un evento adjunto para actualizar algo de texto en la página una vez que cambian. Yo uso jQuery que es realmente genial :)

También utilizo el marco Microsofts Ajax , utilizando UpdatePanel. La razón por la que hago eso es que ciertos elementos se crean en la página basándose en alguna lógica del lado del servidor. Realmente no quiero explicar por qué uso UpdatePanel, incluso si pudiera (se puede con bastante esfuerzo) reescribirlo para usar solo jQuery , todavía quiero ese UpdatePanel.

Probablemente lo haya adivinado: una vez que tengo una devolución en el UpdatePanel, los eventos de jQuery dejan de funcionar. De hecho, esperaba esto, ya que la "devolución de datos" no es realmente una devolución de datos nueva, por lo que mi código en document.ready que une los eventos no se activará nuevamente. También confirmé mi sospecha leyendo sobre ello en las bibliotecas de ayuda de jQuery.

De todos modos, me queda el problema de volver a vincular mis controles después de que UpdatePanel haya terminado de actualizar el DOM . Preferiblemente necesito una solución que no requiera agregar más archivos .js (complementos de jQuery) a la página, pero algo tan simple como poder capturar la 'actualización posterior' de UpdatePanel donde puedo simplemente llamar a mi método para volver a enlazar todos los elementos del formulario .

Per Hornshøj-Schierbeck
fuente
Esto es muy similar a esta pregunta: stackoverflow.com/questions/256195/…
Dan Herbert

Respuestas:

85

Dado que está utilizando ASP.NET AJAX, tendrá acceso a un pageLoadcontrolador de eventos, al que se llama cada vez que la página se vuelve a publicar, ya sea total o parcial desde un UpdatePanel. Solo necesita poner la función en su página, no se requiere conexión.

function pageLoad(sender, args)
{
   if (args.get_isPartialLoad())
   {
       //Specific code for partial postbacks can go in here.
   }
}
Phil Jenkins
fuente
1
No hay problema, esa es solo una forma de hacerlo por cierto. Si necesita más flexibilidad, consulte el evento endRequest en la clase PageRequestManager.
Phil Jenkins
¡Increíble! Reemplacé mi jquery $ (document) .ready con su pageLoad (sin el bloque if) y resolvió mi problema.
Chris
10
Precaución: sólo se ejecuta una función "pageLoad" en la página, la última definida. Entonces, si las acciones que deben ejecutarse residen en diferentes controles, existen formas más fáciles de lograr el comportamiento requerido, como "Sys.Application.add_load".
Paulius
23

O puede verificar la última funcionalidad en vivo de jQuery a través del on()método.

Jorge
fuente
Esta fue la mejor solución para mí, ya que gran parte de mi marcado jQuery está encapsulado dentro de varios controles de usuario en la página.
Kyle B.
1
¿Puedes publicar un ejemplo con datepicker?
Perica Zivkovic
Solo estaba usando "on" para enlazar a una lista desplegable dentro de un panel que activa la publicación asíncrona. NO estaba funcionando hasta que también incluí la respuesta anterior de @Phil Jenkins. No estoy seguro de si hace una diferencia si se trata de una publicación asíncrona o una publicación completa, pero el encendido. aglutinante no lo estaba manejando después de la publicación.
Casey
22
Sys.Application.add_load(initSomething);
function initSomething()
{
  // will execute on load plus on every UpdatePanel postback
}
Paulius
fuente
14

A partir de jQuery 1.7, la forma recomendada de hacer esto es usar la sintaxis .on () de jQuery .

Sin embargo, asegúrese de configurar el evento en el objeto del documento , no en el objeto DOM en sí. Por ejemplo, esto se romperá después de la devolución de datos de UpdatePanel :

$(':input').on('change', function() {...});

... porque las ': entradas' se han reescrito. Haz esto en su lugar:

$(document).on('change', ':input', function() {...});

Mientras el documento esté disponible, cualquier entrada (incluidas las de las actualizaciones de UpdatePanel) activará el controlador de cambios.

lambinator
fuente
Increíble ! (el documento) funcionó de maravilla usando lo siguiente .... $ (documento) .on ('click', '# tagsAdd', function () sin importar cuántos paneles de actualización tenga dividiendo el contenido de la página :) Thx
Martin Sansone - MiOEE
9

Utilice el siguiente código

Sys.WebForms.PageRequestManager.getInstance().add_pageLoaded(pageLoaded);

function pageLoaded(sender, args) {
    var updatedPanels = args.get_panelsUpdated();
    // check if Main Panel was updated 
    for (idx = 0; idx < updatedPanels.length; idx++) {
        if (updatedPanels[idx].id == "<%=upMain.ID %>") {
            rebindEventsForMainPanel();
            break;
        }
    }
}
shatl
fuente
8

Puede usar jQuery y la delegación de eventos. Básicamente, enganche los eventos a los contenedores en lugar de a cada elemento y consulte el evento event.target y ejecute el script basándose en eso.

Tiene múltiples beneficios, ya que reduce el ruido del código (no es necesario volver a enlazar). También es más fácil para la memoria del navegador (menos eventos vinculados al DOM).

Ejemplo rápido aquí .

Complemento jQuery para una fácil delegación de eventos.

PD: Estoy 99% seguro de que la delegación estará en el núcleo de jQuery en la próxima versión.

cuadrado rojo
fuente
5

Use el siguiente código, debe validar que el control usará el selector de datos:

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

         Sys.WebForms.PageRequestManager.getInstance().add_endRequest(addDataPicker); 
         function addDataPicker(sender, args)
         {
            var fchFacturacion = document.getElementById('<%= txtFechaFacturacion.ClientID %>');
            if (fchFacturacion != null) {
               $(fchFacturacion).datepicker({ onSelect: function () { }, changeMonth: true, changeYear: true, showOn: 'button', buttonImage: '../Imagenes/calendar.gif', buttonImageOnly: true});}
         } 

    </script>

     <asp:UpdatePanel ID="upEjem" runat="server" UpdateMode="Conditional">
       <ContentTemplate>
              <div id="div1" runat="server" visible="false">
                  <input type="text" id="txtFechaFacturacion" 
                      name="txtFechaFacturacion" visible="true"
                      readonly="readonly" runat="server" />
              </div>
       </ContentTemplate>
     </asp:UpdatePanel>
rocke_amiga
fuente
4

         <script type="text/javascript">
             function pageLoad() {

                 if (Sys.WebForms.PageRequestManager.getInstance().get_isInAsyncPostBack()) {


       }

            </script>

        </ContentTemplate>
    </asp:UpdatePanel>

en el "si" puede poner el código que necesita ejecutar cada vez que el panel de actualización hace AsyncPostBack.

civanm
fuente
2

Vincula tus eventos usando el nuevo método 'en vivo' de jQuery. Unirá eventos a todos sus elementos presentes y también a todos los futuros. Cha ching! :)

John Strickler
fuente