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.