Disable control after AsyncPostBack using jQuery

A revision was requested to an older NET 2.0 WebSite that uses a Telerik Tab and MultiPage control and the main page was wrapped in an UpdatePanel. The last tab (View Rates) displayed an insurance quote with a pair of Accept buttons at the top and bottom of the page to save the quote to the database. The revision was simple enough, disable the Accept button when clicked to prevent saving duplicate copies of the quote. Note: There is a quirk with disabling an asp button control, it also cancels the postback.

Dave Ward posted a great article about this Disable a button control during postback a while ago, so I changed the markup for the top button like this.

<asp:Button ID="btnAccept" runat="server" Text="Accept"
    OnClientClick="this.disabled=true; this.value='Saving...';"
    UseSubmitBehavior="false"
    OnClick="btnAccept_Click" />

That worked great, now I just needed to do the same thing to the other button. Well, the second button turned out to be a “Next” button allowing the user to switch tabs until they reach the last one, View Rates, at which point it doubled as an Accept button. This prevented me from leveraging the same technique as before so I decided to use jQuery to handle both buttons. However, I couldn’t just wire up the event handlers for the buttons using the standard jQuery document.ready function because each Tab/Next button clicked, caused an Ajax Postback which replaces the updatepanel contents, removing the event handlers. To solve that issue the handlers must be re-added at the end of every Ajax request.

JavaScript similar to the following was added that uses the PageRequestManager class to re-add the handlers.

// Use the PageRequestManger class to access the page life cycle events
Sys.WebForms.PageRequestManager.getInstance().add_endRequest(EndRequest);

$(function () {
    // Document ready bindings
});

// called at the end of the Ajax request
function EndRequest(sender, args) {
    BindEvents();
    // Other logic
}

function BindEvents() {
    // Disable the Accept and Next buttons and submit
    $("[id $='btnAccept']").click(function () {
        $(this).attr("disabled","true").val("Saving...");
        $("[id $='btnNext']").attr("disabled","true").val("Saving...");
        __doPostBack(this.id, '');
    });

    // Only wire the Next button if its text is 'Accept'
    // as its normal behavior is moving to the next tab.
    var btnNext = $("[id $='btnNext']");

    if( btnNext.val() == "Accept" ) {
        // Disable the Next and Accept buttons and submit
        btnNext.click(function() {
            $(this).attr("disabled","true").val("Saving...");
            $("[id $='btnAccept']").attr("disabled","true").val("Saving...");
            __doPostBack(this.id, '');
        });
    }
}

Another option that’s available if you don’t want to disable or hide the button is using the PageRequestManager initializeRequest event to check whether there’s already a AsyncPostback in progress. If so, the subsequent button click request can be cancelled using code similar to this.

Sys.WebForms.PageRequestManager.getInstance().add_initializeRequest(PostBackStatus);

function PostBackStatus(sender, args) {
    var prm = Sys.WebForms.PageRequestManager.getInstance()

    if( prm.get_isInAsyncPostBack() ) {
        // cancel the request
        args.set_cancel(true);
   }
}

Even though the solution only required a few lines of jQuery, it could have been avoided if the requester would have allowed the buttons to be hidden instead of disabled (hiding a button does not prevent the submit behavior). However, that wasn’t an option in this case.

Tags: , , ,

Leave a Reply