jQuery Event Binding vs. ASP.NET AJAX UpdatePanel

UPDATE (12/5/2008): An alternative solution to this issue is found in a more recent post here:
http://www.thegrubbsian.com/2008/12/jquery-vs-the-aspnet-update-panel-revisited.html

While this is a simple topic, it is one that tripped me up and since the documentation for ASP.NET AJAX is pretty poor, I thought I'd share how I worked it out.

One of the great advantages of using a JavaScript library like jQuery is easy event binding.  In jQuery you can bind an event in a cross-browser compliant manner with very little code:

$("someElement").click(function() { alert('I'm Clicked!');});

Another convenience of modern JS libraries is a loaded event, basically detecting when the browser has finished receiving and parsing the DOM from the server.  For example, in jQuery we can test for DOM completion thusly:

$(window).ready(function() { ... });

Anything within the function here will be executed only after the entire DOM has been downloaded and parsed by the rendering engine.

Now, when you wrap parts of markup with an ASP.NET AJAX UpdatePanel you create a scenario in which a certain portion of the DOM will be reloaded asynchronously while other parts are not.  Even though you will often be merely updating nodes within this area of the DOM, the UpdatePanel is heavy handed…it basically just wipes out whatever was in there and replaces it fresh from the server.  When this happens all your fancy events bound to those elements are blown away.  Thanks UpdatePanel!

Happily, there is a solution that works with any library, not just jQuery.  You will need to abstract your jQuery event bindings away from their handlers into new JS functions.  For example:

$(window).ready(function() {
    $("#someElement").click(function() {
        alert('I've been clicked!');
    });
});

would become:

$(window).ready(function() {
    $("#someElement").click(function() { SomeElementClicked() });
});

function SomeElementClicked() {
    alert('I've been clicked!');
}

Next, we need to replace the jQuery "ready" block with a function that automatically gets called by the ASP.NET AJAX client framework whenever a postback occurs (sync or async).  So our script would now be:

Sys.Application.add_load(WireEvents);

function WireEvents() {
    $("#someElement").click(function() { SomeElementClicked() });
}

function SomeElementClicked() {
    alert('I've been clicked!');
}

Now you can continue to use jQuery to bind events (and skip using the convoluted ASP.NET AJAX way) and use the UpdatePanel to surround jQuery bound DOM elements.

Category: ASP.NET, jQuery 8 comments »

8 Responses to “jQuery Event Binding vs. ASP.NET AJAX UpdatePanel”

  1. Kevin McGlynn

    I’m trying to implement this with mixed results. I fear being a php developer trying to implement jquery elements on a .Net frontend, has left me confused with a few steps.
    Is all code js/html contained in an UpdatePanel? Do you have an example?
    Thanks

  2. JC Grubbs

    It depends, of course, on what you are trying to accomplish. If you want to load a page, bind some events to DOM elements and then refresh those elements with an Update Panel you’re going to have to rebind those events every time the Update Panel refreshes.
    In effect, the Update Panel is totally removing all of the DOM tree that it contains and rebuilding it on every refresh. This causes all your previously bound JS events to be lost.
    Sys.Application.add_load() and other ASP.NET AJAX methods can give you a hook to re-bind your events after an Update Panel has finished reloading.

  3. Luke Venediger

    Thanks!! This worked for me.
    I kept my initialisation routine at the bottom of my javascript file:
    $(function() { MyLib.Initialise(); });
    And then added the add_load() call to my Initialise function:
    return {
    Initialise: function() {
    BindEvents();
    // Make sure the update panel re-initialises our events
    Sys.Application.add_load(BindEvents);
    }
    }
    Cheers,
    Luke

  4. roryok

    I think its a little neater (and easier) to have WireEvents() called by $(window).ready directly.
    Your new code would look like this
    $(window).ready(function(){WireEvents()});
    Sys.Application.add_load(WireEvents);
    function WireEvents() {
    $(“#someElement”).click(function() { SomeElementClicked() });
    }
    function SomeElementClicked() {
    alert(‘I’ve been clicked!’);
    }
    Also, in this context, its not really necessary to abstract the event bindings, since we’re setting them up using the same method. so it could be even neater:
    $(window).ready(function(){WireEvents()});
    Sys.Application.add_load(WireEvents);
    function WireEvents() {
    $(“#someElement”).click(function() { alert(‘I’ve been clicked!’)});
    }

  5. Justin

    Many thanks, very helpful.

  6. Jake

    Thanks for the tip!!!!
    You can also place a call to the WireEvents() function (or whatever you decide to name it) in a function named pageLoad().
    ASP.NET automatically wire up the pageLoad() function as an Application.Load handler (http://encosia.com/2007/08/01/simplify-aspnet-ajax-client-side-page-initialization/)
    In one of my applications, I call WireEvents() inside my pageLoad() function whether it exists or not. If it does not exist, my Try..Catch captures the exception silently.
    Thanks again!!!

  7. mosabusan

    Great. Like magic my app worked again. Thank you.

  8. Ranjit

    Simple and effective.


Leave a Reply



Back to top