it-swarm.com.de

jQuery $ (document) .ready und UpdatePanels?

Ich verwende jQuery, um einige Mouseover-Effekte mit Elementen zu verbinden, die sich in einem UpdatePanel befinden. Die Ereignisse sind an $(document).ready gebunden. Zum Beispiel:

$(function() {    
    $('div._Foo').bind("mouseover", function(e) {
        // Do something exciting
    });    
});

Das funktioniert natürlich beim ersten Laden der Seite gut, aber wenn das UpdatePanel eine teilweise Aktualisierung der Seite durchführt, wird es nicht ausgeführt und die Mouseover-Effekte funktionieren nicht mehr im UpdatePanel. 

Was ist der empfohlene Ansatz für die Verkabelung in jQuery, nicht nur beim ersten Laden der Seite, sondern jedes Mal, wenn ein UpdatePanel eine teilweise Aktualisierung der Seite auslöst? Sollte ich den ASP.NET-Ajax-Lebenszyklus anstelle von $(document).ready verwenden?

461
Herb Caudill

Ein UpdatePanel ersetzt den Inhalt des Update-Bereichs bei einem Update vollständig. Dies bedeutet, dass die von Ihnen abonnierten Ereignisse nicht mehr abonniert werden, da sich in diesem Aktualisierungsbereich neue Elemente befinden.

Was ich dagegen getan habe, ist die erneute Anmeldung der Ereignisse, die ich nach jedem Update benötige. Ich verwende $(document).ready() für das erstmalige Laden. Dann verwende ich den PageRequestManager von Microsoft (verfügbar, wenn sich auf Ihrer Seite ein Aktualisierungsfenster befindet), um jedes Update erneut zu abonnieren. 

$(document).ready(function() {
    // bind your jQuery events here initially
});

var prm = Sys.WebForms.PageRequestManager.getInstance();

prm.add_endRequest(function() {
    // re-bind your jQuery events here
});

Die Variable PageRequestManager ist ein Javascript-Objekt, das automatisch verfügbar ist, wenn auf der Seite ein Aktualisierungsfenster angezeigt wird. Sie müssen nichts weiter als den obigen Code tun, um ihn verwenden zu können, solange das UpdatePanel auf der Seite angezeigt wird.

Wenn Sie eine detailliertere Steuerung benötigen, übergibt dieses Ereignis Argumente, die der Art der Übergabe von .NET-Ereignissen ähneln, (sender, eventArgs). So können Sie sehen, was das Ereignis ausgelöst hat, und nur bei Bedarf neu verbinden.

Hier ist die neueste Version der Dokumentation von Microsoft: msdn.Microsoft.com/.../bb383810.aspx


Eine bessere Option, die Sie je nach Ihren Bedürfnissen haben, ist die Verwendung von jQuery .on() . Diese Methoden sind effizienter als das erneute Abonnieren von DOM-Elementen bei jeder Aktualisierung. Lesen Sie die gesamte Dokumentation, bevor Sie diesen Ansatz verwenden, da er möglicherweise Ihren Anforderungen entspricht. Es gibt eine Vielzahl von jQuery-Plugins, deren Verwendung für die Verwendung von .delegate() oder .on() unangemessen wäre. In diesen Fällen ist es besser, sich erneut zu abonnieren.

527
Dan Herbert
<script type="text/javascript">

        function BindEvents() {
            $(document).ready(function() {
                $(".tr-base").mouseover(function() {
                    $(this).toggleClass("trHover");
                }).mouseout(function() {
                    $(this).removeClass("trHover");
                });
         }
</script>

Der Bereich, der aktualisiert werden soll.

<asp:UpdatePanel...
<ContentTemplate
     <script type="text/javascript">
                    Sys.Application.add_load(BindEvents);
     </script>
 *// Staff*
</ContentTemplate>
    </asp:UpdatePanel>
158
Barbaros Alp

Benutzersteuerung mit jQuery in einem UpdatePanel

Dies ist keine direkte Antwort auf die Frage, aber ich habe diese Lösung zusammengestellt, indem ich die Antworten gelesen habe, die ich hier gefunden habe, und ich dachte, jemand könnte es nützlich finden.

Ich habe versucht, einen jQuery-Textarea-Limiter in einem User Control zu verwenden. Dies war schwierig, da das Benutzersteuerelement in einem UpdatePanel ausgeführt wird und seine Bindungen beim Rückruf verloren gingen.

Wenn es sich nur um eine Seite handelte, hätten die Antworten hier direkt angewendet. Benutzersteuerelemente haben jedoch keinen direkten Zugriff auf das Head-Tag und auch keinen direkten Zugriff auf das UpdatePanel, wie einige Antworten annehmen. 

Am Ende habe ich diesen Skriptblock ganz oben in das Markup meines User Controls eingefügt. Für die anfängliche Bindung wird $ (document) .ready verwendet, und dann wird prm.add_endRequest von dort verwendet:

<script type="text/javascript">
    function BindControlEvents() {
        //jQuery is wrapped in BindEvents function so it can be re-bound after each callback.
        //Your code would replace the following line:
            $('#<%= TextProtocolDrugInstructions.ClientID %>').limit('100', '#charsLeft_Instructions');            
    }

    //Initial bind
    $(document).ready(function () {
        BindControlEvents();
    });

    //Re-bind for callbacks
    var prm = Sys.WebForms.PageRequestManager.getInstance(); 

    prm.add_endRequest(function() { 
        BindControlEvents();
    }); 

</script>

Also ... Ich dachte nur jemand möchte wissen, dass das funktioniert.

62
Brian MacKay

Aktualisieren Sie auf jQuery 1.3 und verwenden Sie:

$(function() {

    $('div._Foo').live("mouseover", function(e) {
        // Do something exciting
    });

});

Hinweis: Live funktioniert mit den meisten Ereignissen, aber nicht allen. Es gibt eine vollständige Liste in der Dokumentation .

33
svinto

Sie könnten auch versuchen:

<asp:UpdatePanel runat="server" ID="myUpdatePanel">
    <ContentTemplate>

        <script type="text/javascript" language="javascript">
        function pageLoad() {
           $('div._Foo').bind("mouseover", function(e) {
               // Do something exciting
           });
        }
        </script>

    </ContentTemplate>
</asp:UpdatePanel>

, da pageLoad () ein ASP.NET-Ajax-Ereignis ist, das jedes Mal ausgeführt wird, wenn die Seite auf Clientseite geladen wird.

20
Daniel Hursan

Meine Antwort? 

function pageLoad() {

  $(document).ready(function(){

usw.

Arbeitete wie ein Zauber, bei dem einige andere Lösungen kläglich versagten.

16
Jono

Das hat für mich funktioniert:

$(document).ready(function() {

    // Do something exciting

    var prm = Sys.WebForms.PageRequestManager.getInstance();

    prm.add_endRequest(function() {
        // re-bind your jQuery events here
    });

});
7
Turbojohan

Ich würde einen der folgenden Ansätze verwenden:

  1. Schließen Sie die Ereignisbindung in eine Funktion ein und führen Sie sie jedes Mal aus, wenn Sie die Seite aktualisieren. Sie können die Ereignisbindung immer für bestimmte Elemente enthalten, um Ereignisse nicht mehrmals an dieselben Elemente zu binden.

  2. Verwenden Sie das livequery plug-in, das im Grunde die Methode eins automatisch für Sie durchführt. Ihre Präferenz kann variieren, je nachdem, wie viel Kontrolle Sie für die Ereignisbindung haben möchten.

7
Eran Galperin

Wenn $(document).ready(function (){...}) nach dem Zurückschreiben der Seite nicht funktioniert, verwenden Sie die JavaScript-Funktion pageLoad in Asp.page wie folgt: 

<script type="text/javascript" language="javascript">
function pageLoad() {
// Initialization code here, meant to run once. 
}
</script>
6
Pradeep More

funktion pageLoad () ist in dieser Situation sehr gefährlich. Eventuell werden Ereignisse mehrmals verdrahtet. Ich würde mich auch von .live () fernhalten, da es an das Dokumentelement angehängt wird und die gesamte Seite durchlaufen muss (langsam und beschissen). 

Die beste Lösung, die ich bisher gesehen habe, ist die Verwendung der Funktion jQuery .delegate () auf einem Wrapper außerhalb des Update-Panels und die Verwendung von Bubbling. Abgesehen davon können Sie die Handler immer mit der Ajax-Bibliothek von Microsoft verbinden, die für UpdatePanels entwickelt wurde. 

6
Norm

FWIW, ich habe ein ähnliches Problem mit mootools erlebt. Das erneute Anhängen meiner Ereignisse war der richtige Schritt, musste aber am Ende der Anfrage erledigt werden

var prm = Sys.WebForms.PageRequestManager.getInstance();
prm.add_endRequest(function() {... 

Es ist nur etwas zu beachten, wenn beginRequest Sie dazu veranlasst, JS-Ausnahmen mit Nullreferenz zu erhalten.

Prost

4
SanjayU

Dies ist ein großartiges Plugin zur Verwendung mit Update-Panels:

http://updatepanelplugin.codeplex.com/

4
A_Surtees

Ich hatte ein ähnliches Problem und stellte fest, dass es am besten war, auf Event Bubbling und Eventdelegation zurückzugreifen. Das Schöne an der Delegierung von Ereignissen ist, dass Sie nach der Einrichtung von AJAX keine Ereignisse erneut binden müssen.

Was ich in meinem Code mache, ist das Einrichten eines Delegaten im übergeordneten Element des Aktualisierungsfensters. Dieses übergeordnete Element wird bei einem Update nicht ersetzt. Daher ist die Ereignisbindung nicht betroffen.

Es gibt eine Reihe guter Artikel und Plugins, die die Ereignisdelegierung in jQuery behandeln, und die Funktion wird wahrscheinlich in die 1.3-Version eingebunden. Der Artikel/Plugin, den ich als Referenz verwende, lautet:

http://www.danwebb.net/2008/2/8/event-delegation-made-easy-in-jquery

Wenn Sie erst einmal verstanden haben, was passiert, denke ich, dass dies eine viel elegantere Lösung ist, die zuverlässiger ist, als sich daran zu erinnern, Ereignisse nach jedem Update neu zu binden. Dies hat auch den zusätzlichen Vorteil, dass Sie ein Ereignis zum Entbinden freigeben können, wenn die Seite entladen wird.

4
Joe Brinkman
pageLoad = function () {
    $('#div').unbind();
    //jquery here
}

Die pageLoad-Funktion ist perfekt für diesen Fall, da sie beim ersten Laden der Seite und bei jedem Updatepanel async postback ausgeführt wird. Ich musste nur die Unbind-Methode hinzufügen, damit die Jquery auf postbacks von updatepanel funktioniert.

http://encosia.com/document-ready-and-pageload-are-not-the-same/

3
Duane

Meine Antwort basiert auf allen obigen Expertenkommentaren. Nachfolgend finden Sie den folgenden Code, mit dem jeder sicherstellen kann, dass bei jedem Postback und bei jedem asynchronen Postback der JavaScript-Code weiterhin ausgeführt wird.

In meinem Fall hatte ich eine Benutzersteuerung auf einer Seite. Fügen Sie einfach den folgenden Code in Ihr Benutzersteuerelement ein.

<script type="text/javascript"> 
        var prm = Sys.WebForms.PageRequestManager.getInstance();
    prm.add_endRequest(EndRequestHandler);
    function EndRequestHandler(sender, args) {
        if (args.get_error() == undefined) {
            UPDATEPANELFUNCTION();
        }                   
    }

    function UPDATEPANELFUNCTION() {
        jQuery(document).ready(function ($) {
            /* Insert all your jQuery events and function calls */
        });
    }

    UPDATEPANELFUNCTION(); 

</script>

Update Panel ersetzt Ihre Jquery nach jedem Laden durch die eingebauten Scriptmanager-Skripts. Es ist besser, wenn Sie die Instanzmethoden von pageRequestManager wie folgt verwenden ...

Sys.WebForms.PageRequestManager.getInstance().add_endRequest(onEndRequest)
    function onEndRequest(sender, args) {
       // your jquery code here
      });

es wird gut funktionieren ... 

2
Rohit Sharma

Als Antwort auf Brian MacKays Antwort:

Ich füge das JavaScript über den ScriptManager in meine Seite ein, anstatt es direkt in den HTML-Code des UserControls einzufügen. In meinem Fall muss ich zu einem Formular scrollen, das sichtbar gemacht wird, nachdem das UpdatePanel beendet und zurückgegeben wurde. Dies geht in den Code hinter der Datei. In meinem Beispiel habe ich bereits die Variable prm auf der Hauptinhaltsseite erstellt.

private void ShowForm(bool pShowForm) {
    //other code here...
    if (pShowForm) {
        FocusOnControl(GetFocusOnFormScript(yourControl.ClientID), yourControl.ClientID);
    }
}

private void FocusOnControl(string pScript, string pControlId) {
    ScriptManager.RegisterStartupScript(this.Page, this.Page.GetType(), "focusControl_" + pControlId, pScript, true);
}

/// <summary>
/// Scrolls to the form that is made visible
/// </summary>
/// <param name="pControlId">The ClientID of the control to focus on after the form is made visible</param>
/// <returns></returns>
private string GetFocusOnFormScript(string pControlId) {
    string script = @"
    function FocusOnForm() {
        var scrollToForm = $('#" + pControlId + @"').offset().top;
        $('html, body').animate({ 
            scrollTop: scrollToForm}, 
            'slow'
        );
        /* This removes the event from the PageRequestManager immediately after the desired functionality is completed so that multiple events are not added */
        prm.remove_endRequest(ScrollFocusToFormCaller);
    }
    prm.add_endRequest(ScrollFocusToFormCaller);
    function ScrollFocusToFormCaller(sender, args) {
        if (args.get_error() == undefined) {
            FocusOnForm();
        }
    }";
    return script;
}
0
fujiiface
Sys.Application.add_load(LoadHandler); //This load handler solved update panel did not bind control after partial postback
function LoadHandler() {
        $(document).ready(function () {
        //rebind any events here for controls under update panel
        });
}
0
Tony Dong

Verwenden Sie das folgende Skript und ändern Sie den Hauptteil des Skripts entsprechend.

       <script>
        //Re-Create for on page postbacks
        var prm = Sys.WebForms.PageRequestManager.getInstance();
        prm.add_endRequest(function () {
           //your codes here!
        });
    </script>
0
mzonerz