56

I have a button like the following,

<asp:Button ID="pagerLeftButton" runat="server" OnClientClick="disable(this)" onclick="pager_Left_Click" Text="<" />

When I use my button like that, onclick is not firing. When I remove OnClientClick, then onclick is firing.

What I need to do is, disable the button during the postback and enable it after the postback ends.

Edit: Additional information:

I added break point to my firing functions is c# part and I am debugging, they are not firing for sure. Those functions are like

protected void pager_Left_Click(object sender, EventArgs e)
{
//Do smthing.
}
protected void pager_Right_Click(object sender, EventArgs e)
{
//Do smthing.
}

and when I click my button, it is disabled for 1-2 seconds and automatically enabled, but I am not sure why it is enabled. I didn't add any part for it to be enabled again.

stckvrflw
  • 1,489
  • 3
  • 22
  • 37

7 Answers7

104

From this article on web.archive.org :

The trick is to use the OnClientClick and UseSubmitBehavior properties of the button control. There are other methods, involving code on the server side to add attributes, but I think the simplicity of doing it this way is much more attractive:

<asp:Button runat="server" ID="BtnSubmit"  OnClientClick="this.disabled = true; this.value = 'Submitting...';"   UseSubmitBehavior="false"  OnClick="BtnSubmit_Click"  Text="Submit Me!" />

OnClientClick allows you to add client side OnClick script. In this case, the JavaScript will disable the button element and change its text value to a progress message. When the postback completes, the newly rendered page will revert the button back its initial state without any additional work.

The one pitfall that comes with disabling a submit button on the client side is that it will cancel the browser’s submit, and thus the postback. Setting the UseSubmitBehavior property to false tells .NET to inject the necessary client script to fire the postback anyway, instead of relying on the browser’s form submission behavior. In this case, the code it injects would be:

__doPostBack('BtnSubmit','')

This is added to the end of our OnClientClick code, giving us this rendered HTML:

<input type="button" name="BtnSubmit"  onclick="this.disabled = true; this.value ='Submitting...';__doPostBack('BtnSubmit','')"  value="Submit Me!" id="BtnSubmit" />

This gives a nice button disable effect and processing text, while the postback completes.

Community
  • 1
  • 1
Vinay Pandey
  • 8,589
  • 9
  • 36
  • 54
  • 6
    This is the correct answer. You should edit your answer to include the information from the article. (`UseSubmitBehavior="false"`) – SLaks Jan 28 '10 at 14:29
  • @Sam, my answer to the question was link to the article but was asked by others on SO to include content. Anyways have included the link. Thanks – Vinay Pandey May 29 '13 at 03:38
  • @VinayPandey, you're welcome! I still think the formatting of your answer doesn't make it very clear that you're quoting someone else. I've suggested an edit to the answer to show you what I mean. – Sam May 29 '13 at 04:19
  • 1
    A disadvantage of this approach is that the button no longer works when JavaScript is disabled or unavailable. – Sam May 29 '13 at 04:41
  • @Sam, thanks for the edit, is there way to do the same without javascript? – Vinay Pandey May 29 '13 at 05:00
  • @VinayPandey, no problem. Yes; see [my answer](http://stackoverflow.com/a/16805363/238753) for an example. – Sam May 29 '13 at 05:19
  • It looks to me, btw, that for VB.NET you don't need to set the OnClick event, because you have the Handles keyword on the event handler sub in the codebehind. – John Mar 03 '17 at 20:17
  • Which event will be called first 'onClick' or 'onClientClick' ? – Pranav Bilurkar Jun 28 '17 at 07:36
  • if you choose to add confirmation do something like this. `` – nishantvodoo Feb 08 '19 at 16:20
  • @PPB onClientClick fires first. – Grant Johnson Jul 26 '22 at 20:14
16

OnClientClick seems to be very picky when used with OnClick.

I tried unsuccessfully with the following use cases:

OnClientClick="return ValidateSearch();" 
OnClientClick="if(ValidateSearch()) return true;"
OnClientClick="ValidateSearch();"

But they did not work. The following worked:

<asp:Button ID="keywordSearch" runat="server" Text="Search" TabIndex="1" 
  OnClick="keywordSearch_Click" 
  OnClientClick="if (!ValidateSearch()) { return false;};" />
Gaʀʀʏ
  • 4,372
  • 3
  • 39
  • 59
  • This produces `SyntaxError: Unexpected token if` Shouldnt there be a `javascript` protocol on the front of that? – crthompson Jul 14 '14 at 21:17
  • Works fine. thanks ! Js function should `return true` on successful validation otherwise OnClick with not be hit. – Aki Oct 09 '15 at 10:51
  • Simply a clean, beautiful and working solution for `Webforms` newbies :) thanks Garry – Zeeshan Jun 17 '16 at 07:40
  • 1
    This is just bizarre that this works! But it does. Thank you! – Mmm Jun 27 '18 at 21:10
  • I'm not sure as well why did this worked compare to the previous syntax. This also helped me. – jmai Jun 28 '19 at 08:47
8

There are two issues here:

Disabling the button on the client side prevents the postback

To overcome this, disable the button after the JavaScript onclick event. An easy way to do this is to use setTimeout as suggested by this answer.

Also, the OnClientClick code runs even if ASP.NET validation fails, so it's probably a good idea to add a check for Page_IsValid. This ensures that the button will not be disabled if validation fails.

OnClientClick="(function(button) { setTimeout(function () { if (Page_IsValid) button.disabled = true; }, 0); })(this);"

It's neater to put all of this JavaScript code in its own function as the question shows:

OnClientClick="disable(this);"

function disable(button) {
    setTimeout(function () {
        if (Page_IsValid)
            button.disabled = true;
    }, 0);
}

Disabling the button on the client side doesn't disable it on the server side

To overcome this, disable the button on the server side. For example, in the OnClick event handler:

OnClick="Button1_Click"

protected void Button1_Click(object sender, EventArgs e)
{
    ((Button)sender).Enabled = false;
}

Lastly, keep in mind that preventing duplicate button presses doesn't prevent two different users from submitting the same data at the same time. Make sure to account for that on the server side.

Community
  • 1
  • 1
Sam
  • 40,644
  • 36
  • 176
  • 219
  • 10
    Can the down-voters please let me know what's wrong? If I'm wrong, I would like to know so I can remove this answer and learn from my mistakes. Or if you just don't understand my code or the reasoning behind it, please ask. In the latter case, you're doing a disservice to the community by down-voting good advice. – Sam May 30 '13 at 09:26
  • This was the best explanation of the root cause and reasoning behind the very helpful workaround. – DanO Feb 08 '19 at 22:51
6

Vinay (above) gave an effective work-around. What's actually causing the button's OnClick event to not work following the OnClientClick event function is that MS has defined it where, once the button is disabled (in the function called by the OnClientClick event), the button "honors" this by not trying to complete the button's activity by calling the OnClick event's defined method.

I struggled several hours trying to figure this out. Once I removed the statement to disable the submit button (that was inside the OnClientClick function), the OnClick method was called with no further problem.

Microsoft, if you're listening, once the button is clicked it should complete it's assigned activity even if it is disabled part of the way through this activity. As long as it is not disabled when it is clicked, it should complete all assigned methods.

Patrick
  • 61
  • 1
  • 1
2

What if you don't immediately set the button to disabled, but delay that through setTimeout? Your 'disable' function would return and the submit would continue.

Hans Kesting
  • 38,117
  • 9
  • 79
  • 111
1

Your JavaScript is fine, unless you have other scripts running on this page which may corrupt everything. You may check this using Firebug.

I've now tested a bit and it really seems that ASP.net ignores disabled controls. Basically the postback is issued, but probably the framework ignores such events since it "assumes" that a disabled button cannot raise any postback and so it ignores possibly attached handlers. Now this is just my personal reasoning, one could use Reflector to check this in more depth.

As a solution you could really try to do the disabling at a later point, basically you delay the control.disabled = "disabled" call using a JavaTimer or some other functionality. In this way 1st the postback to the server is issued before the control is being disabled by the JavaScript function. Didn't test this but it could work

Juri
  • 32,424
  • 20
  • 102
  • 136
0

function UpdateClick(btn) {

    for (i = 0; i < Page_Validators.length; i++) {

        ValidatorValidate(Page_Validators[i]);

        if (Page_Validators[i].isvalid == false)

            return false;
    }

    btn.disabled = 'false';

    btn.value = 'Please Wait...';

    return true;
}
user3783446
  • 425
  • 5
  • 11