Tuesday, July 13, 2010

jQuery does not work properly after ajax partial postback

Don't get shocked by the title of the post. This is true. Recently I have faced this issue. Let us walkthrough of what we are talking about. We all are familiar with below code. A script manager, update panel and content template. As you see I have placed 2 buttons. One gets binded on document.ready() function and other does a async postback.
<asp:ScriptManager ID="sManager1" runat="server"></asp:ScriptManager>
<asp:UpdatePanel ID="upd1" runat="server">
 <ContentTemplate>
   <asp:Button ID="btnClient" runat="server" Text="jQuery Event" />
   <asp:Button ID="btnServer" runat="server" Text="Server Event" 
   onclick="btnServer_Click" />
  </ContentTemplate>
</asp:UpdatePanel>

Related Post:

jQuery code which binds the click event of "btnClient" button.
$(function()
{
    $("#btnClient").bind('click', function()
    {
        alert('I am clicked');
    });
});
Server side event of "btnServer" button.
protected void btnServer_Click(object sender, EventArgs e)
{
    Thread.Sleep(10000);
}
Just run this page. Click on btnClient and you will see an alert('I am clicked') message. Now click on btnServer event. An async postback occurs. Now again click on btnClient button. Oops!! No alert this time. :(

Well, just for the info that document.ready() event is fired when you DOM is ready. It does not fire on ajax async postback. So it doesn't reattach the functionality to the elements. So what to do now? Well, jQuery has introduced a new function called live() in jQuery 1.3.2 which can solve your purpose.
$(function()
{
    $("#btnClient").live('click', function()
    {
        alert('I am clicked');
    });
});
But live() only works for limited set of functionalities. Like if you have placed a datepicker control on textbox, live() function will not help you to attach it again after async postback.

Well, it's not that difficult to achieve it with Ajax. There are couple of ways to make your jQuery work after async postback.
  1. Create an End_request handler of Ajax and place your document.ready() code inside it.
    <script type="text/javascript" language="javascript">
    Sys.WebForms.PageRequestManager.getInstance().add_endRequest(EndRequest);
    function EndRequest(sender, args)
    {
        if (args.get_error() == undefined) {
                BindEvents();
         }
    }
    function BindEvents()
    {
       $("#btnClientSide").bind('click', function()
       {
             alert('I am clicked');
       });
    }
    
    BindEvents();    
    
    </script>
    
  2. Add a pageLoad() function in the page and put all your jQuery within it. pageLoad() function is available in JavaScript if you are using ASP.NET ajax. AJAX framework automatically wires up any client-side function named pageLoad() as an Application.Load handler. Both examples are same.
    Sys.Application.add_load(LoadHandler); 
    function LoadHandler() { 
     //Your code goes here.
    }
    
    OR
    function pageLoad(sender, args)
    {
        $("#btnClientSide").bind('click', function()
        {
            alert('I am clicked');
        });
    }
    
    This pageLoad function also provides a property args.get_isPartialLoad(), which returns true if it is a partial postback and false if it is normal postback.
So, you can enjoy the power of jQuery along with ASP.NET ajax to create your applications.

Feel free to contact me if you face any problem. I will gladly help you.