Damon Armstrong

Caffeine Induced Tirades about .NET and Life
And don't forget to check out my latest Simple-Talk articles
Add to Technorati Favorites      Add to Google     

Disabling an ASP.NET Button when Clicked

Published Thursday, December 20, 2007 11:55 PM

I was answering a question in the ASP.NET forums on Simple-Talk.com (click here you want to check it out) about how to avoid the issue of users submitting multiple page requests when they click on buttons.  My first inclination was hey, just disable the button after they click it and everything will be just fine.  So I fired up Visual Studio and threw the following code into a page:

<asp:Button runat="server" Text="My Button" OnClientClick="this.disabled=true;" />


And naturally it failed miserably.  Why?  Because nothing works on the first try -- unless fate is trying to store up some catastrophe points to use on you later.  And apparently if you disable a button in the onclick it doesn't post back for reasons that I haven't dug into very far.  Not to be outwitted by HTML, Javascript, .NET, or whatever else you can blame for your problems, I tried a myriad of random ideas until I hit upon this -- instead of disabling the button when you click it, set the onclick event to fire a function that returns false.  So it looks something like this:

<asp:Button runat="server" Text="My Button" OnClientClick="this.onclick=new Function('return false;');" />


This approach effectively disables the button, but doesn't gray it out.  So there you go.  If you want a gray button then this isn't the blog for you, but it does keep people from clicking on it the button more than once.  Naturally, this means that some sticklers out there will whine because the button stays disabled if the request times out or the viewer stops the request manually.  Part of me says leave it disabled as vengeful tribute to the multitudes who quintuple-clicked your button and created a horde of duplicate records for you to delete.  Then there's the other part of me that likes the JavaScript setTimeout function and a bit of a challenge:

<script type="text/javascript"
   
function disableButton(button, resetDelay)
   
{
        button.oldonclick
= button.onclick;
       
button.onclick=noClick; //new Function("return false;";
       
setTimeout("enableButton('"+ button.id + "');" resetDelay);                                    
   
}
   
function noClick()
   
{
        alert
("Chill - You already submitted this page once. "+
               
"Submitting it twice isn't going to make the "
               
"server go faster.  Quit hitting the "+
               
"freakin' button!";
       
return false;
   
}
   
function enableButton(buttonId)
   
{
        var button
= document.getElementById(buttonId);
       
if(button!=null)
       
{
            button.onclick
= button.oldonclick;
       
}
    }
</script>


The disableButton function copies the "standard" onclick method into a fake property of the button for safe keeping, sets the new onclick to the noClick function (which displays a nice message to the user if they DO try to click), then sets up a delayed function call (read--asynchronous method) that executes after a delay that you set when calling the disableButton method (a value of 1000 for the resetDelay = 1 second, so multiply accordingly for your needs).  Here's an example of what it looks like in a button:

<asp:Button runat="server" Text="My Button" OnClientClick="disableButton(this,30000)" />


When you click this button, it gets disabled for 30 seconds.  And if a user clicks on that button in the interim, they even get a little feedback on what's going on.  Just remember, don't blame me when you get fired for pasting the script into your project and forgetting to change the message.

by Damon
Filed Under:

Comments

 

Robyn Page said:

Why mess with the button 'onclick'  at all? Couldn't one just insert a 'return false' on the onSubmit event of the form? I agree that you'd still need the timer device to remove it after a few seconds. It also allows you to disable/enable the button at the same time because it is no longer involved in the 'submit' process.
January 1, 2008 5:26 PM
 

Damon said:

Ouch.  You just had to rain on my parade, didn't you?  Actually, the onsubmit approach is a very good solution for solving the problem for everything on the page and not just for a single button.

The only reason that you may want go with the button approach over the onsubmit approach is on user-controls (or even server controls).  You don't necessarily know if the user contorl is going to end up on a page whose onsubmit contains the appropriate multi-submission stopping code, so including it directly in the button ensures it.  

Of course, I suppose that also means that you could just change the onsubmit of the current form from the button itself, but I haven't tested that as of yet, so I'm not sure if there are any pitfalls to the approach.
January 2, 2008 5:26 PM
 

Robyn Page said:

Here is the code to demonstrate the 'onSubmit' solution. I left out the timer reset just to keep things simple.
January 3, 2008 3:07 AM
 

Robyn Page said:

I also haven't put in the javascript to give the persistance of the button states, but that is pretty simple to do with hidden inputs.

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">

<html>
<head>
<title></title>
<style type="text/css">
<!--
fieldset{
width: 250px;
padding:15px;
}
-->
</style>
</head>
<script type="text/javascript">
var clicked=false
function alreadyClicked()
{
var isItClicked=clicked;
clicked=true;
document.getElementById('submit').disabled=true;
return !isItClicked;
}
</script>
<body>
<fieldset><legend><strong>Contact us</strong></legend>
<form action="formlock.html"
    onsubmit="return alreadyClicked()" method="post">
<textarea rows="5">
</textarea>
<input type="submit" id="submit" value="send">
</form>
</fieldset>

</body>
</html>
January 3, 2008 3:10 AM
 

MoodyCat said:

I encountered this problem a while back... I think what happens is that the OnClick javascript that disables the button fires first, and then when the rest of the action that will result in postback and all that is supposed to be firing, guess what -- the button is disabled and thus unable to continue firing events.  At least, that's what I tell myself as I pace the living room at 2:34 in the morning wondering why this problem is so mind-bogglingly inane.

Our solution looked like Robyn's, but without the disable in the OnSubmit since we didn't want to tempt future compatibility fate by simply moving the disable action elsewhere in a volatile call-stack.
February 26, 2008 12:46 PM
 

Daniel Penrod said:

May 6, 2008 4:40 PM
 

Zarcom said:

One of the ways I've solved this in the past was to set the visibility of the button to hidden onclick.  I also set the visibility to visible on a information panel.  Effectively giving a "please wait..." or hour glass function to the button click.

You can also use the display property depending on how you want the page to act.
July 9, 2008 5:29 PM
You need to sign in to comment on this blog

















<December 2007>
SuMoTuWeThFrSa
2526272829301
2345678
9101112131415
16171819202122
23242526272829
303112345
On the Trail of the Expanding Databases
 It is sometimes difficult for other IT people to understand the constraints that DBAs have to work... Read more...

SQL Server 2008: The New Data Types
 Brad continues his helicopter-level view of the most interesting new features of SQL Server 2008 with a... Read more...

Reporting on Mobile Device Activity Using Exchange 2007 ActiveSync Logs
 In this new column giving practical advice on all things Sys Admin related, Ben Lye takes on the often... Read more...

The Bejeweled Puzzle in SQL
 Alex Kozak provides another SQL puzzle to hone your SQL Skills with.  Read more...

Using Powershell to Generate Table-Creation Scripts
 For all of us who learn best by trying out examples, Bob Sheldon produces a PowerShell script file for... Read more...