views:

3400

answers:

4

I'm trying to handle the submit event of a form element using jQuery.

    $("form").bind("submit", function() {
        alert("You are submitting!");
    });

This never fires when the form submits (as part of a postback, e.g. when I click on a button or linkbutton).

Is there a way to make this work? I could attach to events of the individual elements that trigger the submission, but that's less than ideal - there are just too many possibilities (e.g. dropdownlists with autopostback=true, keyboard shortcuts, etc.)


Update: Here's a minimal test case - this is the entire contents of my aspx page:

<%@ page language="vb" autoeventwireup="false" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"&gt;
<html xmlns="http://www.w3.org/1999/xhtml"&gt;
<head runat="server">
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
        <div>
            <asp:scriptmanager id="ScriptManager" runat="server" enablepartialrendering="true">
                <scripts>
                    <asp:scriptreference path="/Standard/Core/Javascript/Jquery.min.js" />
                </scripts>
            </asp:scriptmanager>
            <p>
                <asp:linkbutton id="TestButton" text="Click me!" runat="server" /></p>
        </div>
    </form>

    <script type="text/javascript">
        $(document).ready(function() {
            alert("Document ready.");
            $("form").submit(function() {
                alert("Submit detected.");
            });
        });
    </script>

</body>
</html>

I get the "Document ready" alert, but not the "Submit detected" when clicking on the linkbutton.

+4  A: 

Yeah, this is annoying. I replace __doPostBack with my own so that I could get submit events to fire.

Iirc, this is an issue when submitting a form via javascript (which calls to __doPostBack do) in IE (maybe other browsers too).

My __doPostBack replacement calls $(theForm).submit() after replicating the default behavior (stuffing values in hidden inputs)

Ken Browning
Hijacking __doPostBack : http://weblogs.asp.net/vga/archive/2004/03/01/NoMoreHijackingOfDoPostBackInWhidbey.aspx
russau
@russau - It's my impression from the article that postback hijacking shouldn't be necessary as of Whidbey (VS2005)?
Herb Caudill
@Herb Well, their cause for hijacking is different than yours. It sounds like their cause has been addressed. Yours definitely has not. If you want jQuery submit events to be fired whenever a postback is initiated by a call to __doPostBack then you'll need to hijack __doPostBack.
Ken Browning
A: 

I don't know how to do it with jQuery, but you could add an OnClientClick property to the ASP.NET control:

<asp:linkbutton id="TestButton" text="Click me!" runat="server" OnClientClick="alert('Submit detected.');" />
R. Bemrose
This doesn't help in my situation. First, if I was going to handle every single control that might trigger a postback, it would be a better solution to use jQuery to capture events on these across the board. But what I need is a global solution on lots of different forms, and I don't want to go back and touch every single control that could possible trigger a postback.
Herb Caudill
+5  A: 

Thanks, @Ken Browning and @russau for pointing me in the direction of hijacking __doPostBack. I've seen a couple of different approaches to this:

  1. Hard-code my own version of __doPostBack, and put it later on the page so that it overwrites the standard one.
  2. Overload Render on the page and inject my own custom code into the existing __doPostBack.
  3. Take advantage of Javascript's functional nature and create a hook for adding functionality to __doPostBack.

The first two seem undesirable for a couple of reasons (for example, suppose in the future someone else needs to add their own functionality to __doPostBack) so I've gone with #3.

This addToPostBack function is a variation of a common pre-jQuery technique I used to use to add functions to window.onload, and it works well:

addToPostBack = function(func) {
    var old__doPostBack = __doPostBack;
    if (typeof __doPostBack != 'function') {
        __doPostBack = func;
    } else {
        __doPostBack = function(t, a) {
            if (func(t, a)) old__doPostBack(t, a);
        }
    }
};

$(document).ready(function() {
    alert("Document ready.");
    addToPostBack(function(t,a) {
        return confirm("Really?")
    });
});

Edit: Changed addToPostBack so that

  1. it can take the same arguments as __doPostBack
  2. the function being added takes place before __doPostBack
  3. the function being added can return false to abort postback
Herb Caudill
+1  A: 

I've had success with a solution with overriding __doPostBack() so as to call an override on form.submit() (i.e. '$('form:first').submit(myHandler)'), but I think it's over-engineered. As of ASP.NET 2.0, the most simple workaround is to:

1.Define a javascript function that you want to run when the form is submitted i.e.

<script type="text/javascript">

function myhandler()
{
    alert('you submitted!');
}

</script>

2.Register your handler function within your codebehind i.e.

protected override void OnLoad(EventArgs e)
{
    base.OnLoad(e);
    ScriptManager.RegisterOnSubmitStatement(Page, Page.GetType(), "myHandlerKey", "myhandler()");
}

That's all! myhandler() will be called from straightforward button-input submits and automatic __doPostBack() calls alike.

James McCormack