Ereignisse in jQuery nach Ajax-Update (Updatepanel) neu binden

80

Ich habe mehrere Eingabe- und Optionselemente auf meiner Seite, an die jeweils (fast) ein Ereignis angehängt ist, um Text auf der Seite zu aktualisieren, sobald sie sich ändern. Ich benutze jQuery, was wirklich sehr, sehr cool ist :)

Ich verwende auch das Microsoft Ajax- Framework und verwende das UpdatePanel. Der Grund, warum ich das tue, ist, dass bestimmte Elemente auf der Seite basierend auf einer serverseitigen Logik erstellt werden. Ich möchte nicht wirklich erklären, warum ich das UpdatePanel verwende - auch wenn es (mit einigem Aufwand) umgeschrieben werden könnte, um nur jQuery zu verwenden, möchte ich dieses UpdatePanel immer noch.

Sie haben es wahrscheinlich erraten - sobald ich ein Postback auf dem UpdatePanel habe, funktionieren die jQuery-Ereignisse nicht mehr. Ich hatte dies tatsächlich erwartet, da das "Postback" nicht wirklich ein neues Postback ist, so dass mein Code in document.ready, der die Ereignisse bindet, nicht erneut ausgelöst wird. Ich habe meinen Verdacht auch bestätigt, indem ich ihn in den jQuery-Hilfebibliotheken nachgelesen habe.

Wie auch immer, ich habe das Problem, meine Steuerelemente erneut zu binden, nachdem das UpdatePanel das DOM aktualisiert hat . Ich benötige vorzugsweise eine Lösung, bei der der Seite keine weiteren .js-Dateien (jQuery-Plug-Ins) hinzugefügt werden müssen, sondern nur die Nachaktualisierung des UpdatePanels, bei der ich einfach meine Methode aufrufen kann, um alle Formularelemente neu zu binden .

Per Hornshøj-Schierbeck
quelle
Dies ist dieser Frage sehr ähnlich: stackoverflow.com/questions/256195/…
Dan Herbert

Antworten:

85

Da Sie ASP.NET AJAX verwenden, haben Sie Zugriff auf einen pageLoadEreignishandler, der jedes Mal aufgerufen wird, wenn die Seite von einem UpdatePanel vollständig oder teilweise zurückgesendet wird. Sie müssen nur die Funktion in Ihre Seite einfügen, es ist keine Verbindung erforderlich.

function pageLoad(sender, args)
{
   if (args.get_isPartialLoad())
   {
       //Specific code for partial postbacks can go in here.
   }
}
Phil Jenkins
quelle
1
Kein Problem - das ist übrigens nur eine Möglichkeit. Wenn Sie mehr Flexibilität benötigen, überprüfen Sie das Ereignis endRequest in der PageRequestManager-Klasse.
Phil Jenkins
Genial! Ich habe mein jquery $ (Dokument) bereits durch Ihr pageLoad (ohne den if-Block) ersetzt und es hat mein Problem gelöst!
Chris
10
Achtung: Auf Seite wird nur eine "pageLoad" -Funktion ausgeführt - die zuletzt definierte. Wenn sich also Aktionen, die ausgeführt werden müssen, auf verschiedenen Steuerelementen befinden, gibt es einfachere Möglichkeiten, das erforderliche Verhalten zu erreichen - wie "Sys.Application.add_load".
Paulius
23

Oder Sie können die Live-Funktionalität von jQuery über die on()Methode überprüfen .

George
quelle
Dies war die beste Lösung für mich, da ein Großteil meines jQuery-Markups in mehreren Benutzersteuerelementen auf der Seite enthalten ist.
Kyle B.
1
Kannst du ein Beispiel mit Datepicker posten?
Perica Zivkovic
Ich habe nur "Ein" zum Binden an eine Dropdown-Liste in einem Bereich verwendet, der asynchrone Post-Triggerung ausführt. Es hat nicht funktioniert, bis ich auch die Antwort oben von @Phil Jenkins aufgenommen habe. Ich bin mir nicht sicher, ob es einen Unterschied macht, ob es sich um einen asynchronen oder einen vollständigen Beitrag handelt, aber das ist ein. Binder handhabte es nicht nach dem Post zurück.
Casey
22
Sys.Application.add_load(initSomething);
function initSomething()
{
  // will execute on load plus on every UpdatePanel postback
}
Paulius
quelle
14

Ab jQuery 1.7 wird empfohlen, die .on () -Syntax von jQuery zu verwenden .

Stellen Sie jedoch sicher, dass Sie das Ereignis für das Dokumentobjekt und nicht für das DOM-Objekt selbst einrichten . Dies wird beispielsweise nach dem UpdatePanel-Postback unterbrochen :

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

... weil die ': Eingänge' neu geschrieben wurden. Tun Sie dies stattdessen:

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

Solange das Dokument vorhanden ist, lösen alle Eingaben (einschließlich der Eingaben aus UpdatePanel-Aktualisierungen) den Änderungshandler aus.

Lambinator
quelle
Genial ! (das Dokument) funktionierte wunderbar mit den folgenden .... $ (Dokument) .on ('click', '# tagsAdd', function (), egal wie viele Update-Panels ich habe, die den Inhalt der Seite aufteilen :) Thx
Martin Sansone - MiOEE
9

Verwenden Sie den folgenden Code

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
quelle
8

Sie können jQuery und Ereignisdelegierung verwenden. Verknüpfen Sie Ereignisse grundsätzlich mit Containern und nicht mit jedem Element und fragen Sie das event.target ab und führen Sie das darauf basierende Skript aus.

Es hat mehrere Vorteile, da Sie das Code-Rauschen reduzieren (kein erneutes Binden erforderlich). Dies schont auch den Browserspeicher (weniger im DOM gebundene Ereignisse).

Kurzes Beispiel hier .

jQuery-Plugin für einfache Ereignisdelegierung.

PS Ich bin mir zu 99% sicher, dass die Delegierung bei der nächsten Version im jQuery-Kern sein wird.

rotes Quadrat
quelle
5

Verwenden Sie den folgenden Code. Sie müssen überprüfen, ob das Steuerelement den Datenpicker verwendet:

    <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
quelle
4

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

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


       }

            </script>

        </ContentTemplate>
    </asp:UpdatePanel>

In das "if" können Sie den Code einfügen, den Sie jedes Mal ausführen müssen, wenn das Updatepanel AsyncPostBack ausführt.

civanm
quelle
2

Binden Sie Ihre Ereignisse mit der neuen Live-Methode von jQuery. Es bindet Ereignisse an alle Ihre gegenwärtigen und auch an alle zukünftigen Elemente. Cha ching! :) :)

John Strickler
quelle