Saturday, August 30, 2008

Ajax.NET: Disable buttons until postback finishes

When developing Web Forms in ASP.NET it is usually the case that we have multiple postbacks on a page. When there are Ajax calls as well it can easily happen that we can have multiple outstanding postbacks - e.g. postback by dropdown list immediately followed by a button click, or simply multiple button clicks. Due to various reasons those calls can end up in different sequence on the server (e.g. network latency). For some we might not care, but for some the sequence might be important.
What I'm showing here is a simple client solution to the problem. It will simply disable buttons while the postback ends thus preventing user to click on them until the postback had finished.


<script language="javascript" type="text/javascript">
//on the page submit we want to disable buttons until the call is finished
// and then reenable them
(function() {
//add on the page load event that will register our scripts
//for all significant events
Sys.Application.add_load(setupButtonDisablers);

function setupButtonDisablers() {
//subscribe to on page load and submit events
//on page load we will enable buttons
Sys.WebForms.PageRequestManager.getInstance().add_pageLoaded(onPageLoad);
//on page submit we will disable them
Sys.WebForms.PageRequestManager.getInstance().add_beginRequest(onSubmit);
//remove setup code so it will never be called again
Sys.Application.remove_load(setupButtonDisablers);
}

//on page load - enable all the relevant buttons
function onPageLoad() {
findAndEnable('<%= MyButton1.ClientId %>');
findAndEnable('<%= MyButton2.ClientId %>');
}

//on page submit - disable all the relevant buttons
function onSubmit() {
findAndDisable('<%= MyButton1.ClientId %>');
findAndDisable('<%= MyButton2.ClientId %>');
}

function findAndDisable(id) {
findAndSetDisabledProperty(id, true);
}

function findAndEnable(id) {
findAndSetDisabledProperty(id, false);
}

//finds and sets disabled property of a searched control
function findAndSetDisabledProperty(id, value) {
var control = $get(id);
if (control) {
control.disabled = value;
}
}
})();
</script>


This is fairly simple code, without comments it would be really short. What it does is subscribing to page submit and load events and is disabling and enabling buttons respectively. Just put it somewhere on a part of the page that will be loaded first time the page loads.
You can make this more complicated if you need to do something specific depending on which element caused the postback by using different signature for onSubmit function. Here is documentation for the beginRequest event. Basically it will accept sender and args and you can use args.get_postBackElement() for example and make decisions what to do with your page elements then - hide them, disable them, animate them, whatever.

And at the end, remember that despite all the effort done on the client side you will always have to handle any eventuality on the server. Always remember, any client input is evil and it has to be validated - in this case postback sequence.

3 comments:

  1. Excellent, just what I was looking for, thank you!

    ReplyDelete
  2. I've used this several times now, really really useful, thanks.

    ReplyDelete
  3. Don't forget. JavaScript is case sensitive so 'ClientId' should be 'ClientID' otherwise you'll get an error.

    ReplyDelete