05 March 2008

How To avoid double click a button on Postback

A common problem in developing with asp.net is the user pressing more than once on a submit button.

One way to avoid this question is to use client side JavaScript to disable the button after the user clicked it. The only problem with this approach is if validators are being used. If the Page is not valid, the button will stay disabled and the user cannot press it again.

There is only one problem: When the button is disabled, the page is not submitted and the button event does not fires on the server.

Fortunately the validation library sets the Page_IsValid to false if validation fails or to true otherwise.
The JavaScript function to change the button image can be written as:

function ToggleButton(button, validationGroup)
{
   // If client validators not active
   if (typeof(Page_Validators) == "undefined")
   {
        SetWaitMode(button);
   }
 
   if (typeof(Page_ClientValidate) == 'function') 
   {
         // Force Page validation 
         Page_ClientValidate(validationGroup);                 
         
         // If validation passed
         if(Page_IsValid)
         {  
            SetWaitMode(button)       
         }
   }
   else
   {
        SetWaitMode(button);
   }
}


function SetWaitMode(button)
{
    button.src = "Shared/images/Wait.gif";
    document.forms[0].submit();
    
    window.setTimeout("DisableButton( '" + button.id  + "')", 0);           
 
}
 
function DisableButton(buttonID) 
{
    window.document.getElementById(buttonID).disabled = true;
}

This solution changes the button image, but doesn't solve the problem, since the user can still press the button.


A more elegant solution is to use two Divs, on with the wait image and other with the button. When the button is pressed it's Div is hidden and the one with the Wait image is shown.



<div id="btnSaveDiv2" runat="server" style="display: none; float: left">
    <img src="Shared/images/Wait.gif"></img>
</div>
<div id="btnSaveDiv1" runat="server" style="display: block; float: left">
    <asp:ImageButton runat="server" ID="btnSave" OnClientClick="javascript:ToggleButton(this, 'AddNewNoteValidationGroup')" ImageUrl="~/Common/images/layout/b_save.gif" OnClick="btnAddNote_Click" ValidationGroup="AddNewNoteValidationGroup" />
</div>


function ToggleButton(button, validationGroup)
{
   // If client validators not active
   if (typeof(Page_Validators) == "undefined")
   {
        DisableButton(button);
   }
 
   if (typeof(Page_ClientValidate) == 'function') 
   {
         // Force Page validation 
         Page_ClientValidate(validationGroup);                 
         
         // If validation passed
         if(Page_IsValid)
         {  
            DisableButton(button)       
         }
   }
   else
   {
        DisableButton(button);
   }
}


function DisableButton(button)
{   
    div1 = window.document.getElementById(button.id + 'Div1');
    div2 = window.document.getElementById(button.id + 'Div2');
    
    div1.style.display = "none";
    div2.style.display = "block";
}

 


This solution works with ASP.Net Ajax and with ASP.Net validators.
The final step is to create a Server Control... :)


References:


Understanding ASP.NET Validation Library


.

6 comments:

Karim said...

Excellent, this works fine for me.
thanks.

Ben said...

Works well, but I get a double validation check and the validation summary pop-up appears twice.

Any ideas?

Generated HTML code looks like this:

<input type="button" name="ctl00$ContentMain$btnSave" value="Save" onclick="ToggleButton(this, ''); ;WebForm_DoPostBackWithOptions(new WebForm_PostBackOptions(&quot;ctl00$ContentMain$btnSave&quot;, &quot;&quot;, true, &quot;&quot;, &quot;&quot;, false, true))" id="ctl00_ContentMain_btnSave" />

Rui said...

Ben,
The code works fine for me.
Something on your code must be causing a double postback.

Jason said...

In Firefox I think this causes a double postback. This free tool fixed the problem for me:

http://encosia.com/downloads/postback-ritalin/

Sharing it wherever I can because it saved my butt. Good luck.

Aziz said...

I can confirm the double validation on both firefox and IE.

If you comment out the force validation step, it doesn't do this, however, there is another problem.

It works okay normally (hides the button or whatnot). But if you first submit and invalid form, then fix it, then submit it, it doesn't hide the button until the SECOND button click.

Still looking into that one. Any help, author?

Rui said...

O don't have that effect in my application.
You must be doing something I am not.
Read the article and understand the code, maybe you can fix the problem.

Regards