Click here to Skip to main content
15,867,488 members
Articles / Web Development / ASP.NET

Using JQuery to intercept the click of an ASP:Button

Rate me:
Please Sign up or sign in to vote.
5.00/5 (1 vote)
31 Mar 2009CPOL4 min read 27.1K   17   1
Using JQuery to intercept the click of an ASP:Button

I was working on an interesting problem today. The architecture of a different project I am working on does not use MVC, but ASP.NET controls. We have separated them into a control/controller model so that business logic interacts with a controller, which passes POCOs to a control, and the control knows how to render them. The control knows no business logic, security, etc., while the controller doesn't understand anything about the UI domain EXCEPT for the fact that it is interacting with something derived from "Control" that lives in Web.UI.

Many of the examples in JQuery show you how to "unbind" an event, but I quickly found this wasn't working for me. What I wanted to do was place a traditional ASP.NET button on the page (quite frankly, the button was already buried in another control, so I wanted to work with this rather than come up with a hack to do a lightweight input button). I needed to intercept the click event, perform a call back, and then based on the result either display an error or allow the originally intended event (a postback) to fire.

After lots of searching, I finally settled with decorating my functions with alerts until I figured out exactly what was going on. So let's get started.

First, the button: easy enough.

ASP.NET
<asp:Button ID="btnExample" runat="server" Text=" Click Me "/>

On the server side, we can do this:

C#
btnExample.OnClick += MyClickHandler; 
...
protected void MyClickHandler(object sender, EventArgs e)
{
   // do something IF all is well 
}

Of course the server should ALSO check what I'm wiring in for validation, but I'm simplifying this for now. Now the fun part. What we want to do is find the button (I'll leave the JQuery up to you - you can search on the button, emit the client id and go on that, etc. In my case, it's the third button in a div with class "buttonBar"). Let's wire this up:

JavaScript
$(document).ready(function() {
       var nextButton = $(".buttonBar input:button:eq(2)");
       window.criteria_postback = $(nextButton).attr("onclick");
       $(nextButton).removeAttr("onclick");
       $(nextButton).unbind().click(function(event) {

           window.criteria_event = event;

           event.preventDefault();

           $(this).attr("disabled", "disabled");
           $(this).val(" Please wait... ");

           //load cmdString with something useful for the server

           WebForm_DoCallback('__Page', cmdString,
       window.Criteria_CallbackHandler, null, null, false);

       });

So let's walk through this. I found for some reason (probably documented somewhere that I just didn't find) that unbinding the click event wasn't working. So instead, I decided to save the existing click event (window.criteria_postback). The reason I save it to the window is because I need to reference it in an eval() expression later on. Microsoft sandboxes evals so they can't see variables unless they are explicitly scoped to global.

Next, we get rid of the attribute (this prevents the event from firing).

Then I wire in my own click event. I SAVE the event to the global space, prevent the default (going through with it), then disable my button so the user doesn't double click.

Finally, I wire in the callback. A few interesting things about callbacks. First, if this code was embedded in a control, I'd need to have a reference to the control instead of the __Page for the control to pick it up. Second, and most importantly, even when you wire your own callback, you MUST let the ClientScript KNOW to listen!. In other words, I told my page to implement ICallbackHandler which exposes:

C#
public void RaiseCallbackEvent(string eventArgument)
{
  // do something with the event from the client
}
...
public string GetCallbackResult()
{
  // return a result to the client
}

Some people mistakenly believe this is enough to be able to capture callbacks, but unless you actually ask for the callback reference, the page/control won't listen! So it's important that even if you don't use the result, you at least make a call like this:

C#
// generate the callback handlers 
Page.ClientScript.GetCallbackEventReference(this, "args", string.Empty, string.Empty);

Now it is happy and listening. We're almost done ... we've intercepted the original postback and saved it, and we've wired in our own callback. In my case, I have a select grid that is harvesting check boxes, so I want to build a light weight list of identifiers. I build that list on the client, then use the callback to send it down and store it on the server for later. A pattern that works well for me with the callback is like this:

C#
private string _callbackResult; 

public void RaiseCallbackEvent(string eventArgument)
{
   try
   {
      ...
      _callbackResult = string.Empty;
   }
   catch(Exception ex) 
   {
     _callbackResult = ex.Message;
   }
}

public string GetCallbackResult()
{
   return _callbackResult; 
}

And now we come back to the client side. Part of the Callback is a delegate to handle the return. In our case, we passed in window.Criteria_CallbackHandler. Here is how we "catch" the result:

JavaScript
window.Criteria_CallbackHandler = function(result, context) {

    if (result == null || result == '') {
        eval(window.criteria_postback + ";onclick(window.criteria_event);");
        return; 
    }
    else {
        alert(result);
    }

    var nextButton = $(".buttonBar input:button:eq(2)");
    
    $(nextButton).val(" Next ");
    $(nextButton).removeAttr("disabled");

}

So what is going on? If I had no issues, I do something interesting. When I saved the "onclick" earlier, you'll find the ASP.NET page wired it in like this:

C#
void onclick(event) { blah; }

So I am basically spitting the function back out in my "eval", then immediately calling it with the event that I saved earlier! This has the result of "business as usual" which in my case is to post to a new page and pick off the list I persisted in the callback to do something with it. Otherwise, I alert the error to the customer (a prettier solution may be to have a div for errors and just write this into the div instead of using the generic alert box), and then regardless, I restore my button so it can be clicked again.

There you go ... buttons, JQuery, and callback handlers all in one post!

Jeremy Likness

This article was originally posted at http://feeds2.feedburner.com/csharperimage

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Program Manager Microsoft
United States United States
Note: articles posted here are independently written and do not represent endorsements nor reflect the views of my employer.

I am a Program Manager for .NET Data at Microsoft. I have been building enterprise software with a focus on line of business web applications for more than two decades. I'm the author of several (now historical) technical books including Designing Silverlight Business Applications and Programming the Windows Runtime by Example. I use the Silverlight book everyday! It props up my monitor to the correct ergonomic height. I have delivered hundreds of technical presentations in dozens of countries around the world and love mentoring other developers. I am co-host of the Microsoft Channel 9 "On .NET" show. In my free time, I maintain a 95% plant-based diet, exercise regularly, hike in the Cascades and thrash Beat Saber levels.

I was diagnosed with young onset Parkinson's Disease in February of 2020. I maintain a blog about my personal journey with the disease at https://strengthwithparkinsons.com/.


Comments and Discussions

 
GeneralMy vote of 5 Pin
BeamingJo28-Jan-13 22:07
BeamingJo28-Jan-13 22:07 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.