jQuery and ASP UpdatePanel Integration

With my latest gig sending me back into the .NET world, I have been busy migrating quite a few of my tools and experience to play nice with ASP.NET sites. One of my favorite open-source tools that is gaining popularity in .NET is jQuery. For several years now, I have been using jQuery heavily to provide rich interaction on websites. When faced with the basic UpdatePanel in ASP.NET, I was presented with a challenge. I wanted a solution that would automatically call jQuery so that new content was properly parsed and updated. Because I had been managing all the AJAX calls in my other development, this was trivially easy to do. UpdatePanel hides all of this inside the ASP AJAX libraries and scripts—making it difficult to figure out where and how to structure my jQuery code. After some research and experimentation, I have a solution up and running on multiple sites now that integrates everything in a very clean manner.

Scoping jQuery Rewrites
The first step is to scope all of the jQuery rewrites. The typical method of integrating jQuery rewrites into a website is to add a document.ready function like so:

$(document).ready(function() {
    $('.content_tab_button').click(function(){
        $('.content_tab_container').load('/newcontent.html');
    });
});

Because the rewrites are only called when the document.ready event fires, integrating with new content pulled in from AJAX needs to be done differently. By placing our rewrites in a new function that recieves the scope being updated, we can have a single initialization handle all of the updating:

function my_initializer(data){
    data.find('.content_tab_button').click(function(){
        $('.content_tab_container').load('/newcontent.html');
        my_initializer($('.content_tab_container').html());
    });
}
$(document).ready(function() {
    my_initializer($(document));
});

Everything is now scoped cleanly. The rewrites are applied to the document when the page is loaded, and the new content when the tab button is clicked. Even if you are not an ASP.NET developer, please take the above scoping strategy with you!

How The UpdatePanel Works
At the highest level, an UpdatePanel refreshes its entire contents when a specificied event occurs within the panel. Server-side, the event triggering the refresh is processed, and the entire page-stae is regenerated. Then, only the content inside the UpdatePanel is pushed out. This is important for any developer using UpdatePanel to understand: UpdatePanel is much more convenient than it is efficient. As a result, our solution must follow that model.

With that in mind, we look to javascript class that is already managing the UpdatePanel, the Sys.WebForms.PageRequestManager class. In this class, we see an event handler for the pageLoad event. In the documentation, you can see that we are able to fetch the update panels that were just updated. In the example, they are looking for a panel with a specific ID. In our case, we are looking at having our rewrites applied to any panel that was updated:

var panels = args.get_panelsUpdated();
if (panels.length > 0) {
    for (i = 0; i < panels.length; i++) {
        my_initializer($(panels[i]));
    }
}

Because we have already scoped our jQuery code, this will work like a charm.

Putting It All Together
We can put all of the code together now, and we'll have a script that will play cleanly with the UpdatePanel:

function my_initializer(data){
    data.find('.content_tab_button').click(function(){
        $('.content_tab_container').load('/newcontent.html');
        my_initializer($('.content_tab_container').html());
    });
}
function my_pageloaded_initializer(sender, args) {
    var panels = args.get_panelsUpdated();
    if (panels.length > 0) {
        for (i = 0; i < panels.length; i++) {
            my_initializer($(panels[i]));
        }
    }
}
$(document).ready(function() {
    my_initializer($(document));
    Sys.WebForms.PageRequestManager.getInstance()
        .add_pageLoaded(my_pageloaded_initializer);
});

All of our rewrites are called once—and only once—during page load and UpdatePanel refresh. Enjoy!

Attachments:
June 1st, 2010