124

I have a simple form with remote=true.

This form is actually on an HTML Dialog, which gets closed as soon as the Submit button is clicked.

Now I need to make some changes on the main HTML page after the form gets submitted successfully.

I tried this using jQuery. But this doesn't ensure that the tasks get performed after some form of response of the form submission.

$("#myform").submit(function(event) {

// do the task here ..

});

How do I attach a callback, so that my code gets executed only after the form is successfully submitted? Is there any way to add some .success or .complete callback to the form?

rahul singh Chauhan
  • 315
  • 1
  • 4
  • 15
geeky_monster
  • 7,914
  • 17
  • 52
  • 81

7 Answers7

122

I just did this -

 $("#myform").bind('ajax:complete', function() {

         // tasks to do 


   });

And things worked perfectly .

See this api documentation for more specific details.

Norman H
  • 2,175
  • 22
  • 27
geeky_monster
  • 7,914
  • 17
  • 52
  • 81
  • 3
    Wow... I just learned something new. Yeah, from the looks of it, this is the most simplest solution. Perhaps, it's even the best. I am an avid Coding Horror reader, and in that blog, Jeff Attwood emphasizes that we should write less code, and this method achieves that. Good find. :) – Sal Rahman Jul 18 '12 at 16:17
  • Please tell me how could you use ajax:complete when binding your form? we can't find any property related to a form like 'ajax:complete'. – kaissun Dec 19 '12 at 17:07
  • Ajax:complete can be attached to any Ajax Event . When the event completes , this is triggered . In my form I used "remote=true" - which means the form gets submitted via Ajax . So u can attach a ajax:complete to the form submissionhttp://api.jquery.com/ajaxComplete/ – geeky_monster Dec 22 '12 at 13:47
  • 7
    And if the `
    ` is submited usually ? (I mean not with Ajax) What can I put in the first argument of `.bind()` ? EDIT : well, I guess `click`. Nvm, sorry. :p
    – 4wk_ Feb 04 '13 at 13:32
  • 10
    beware: this is going to fire your function after the completion of **any** ajax event, not just your form submission (unless I'm mistaken, in which case I'd love for you to provide a link for where you found this) – DMac the Destroyer Jun 07 '13 at 21:02
  • This doesn't seem to work if the form is created dynamically, like in the following: `var form = $("
    ", {'action': 'somepath.html','method':'post'}).bind('ajax:complete', function() {console.log("AJAX COMPLETE");});`
    – MusikPolice Sep 04 '13 at 20:23
  • 19
    "As of jQuery 1.8, the .ajaxComplete() method should only be attached to document" – Meredith Dec 27 '13 at 08:10
  • 1
    Where is 'ajax:complete' defined? In the jQuery docs, it's "ajaxComplete". http://api.jquery.com/Ajax_Events/ – Lawrence I. Siden Feb 12 '14 at 10:03
  • 6
    Didn´t work form me, using normal Form, with a button, but the button calls javascript $('#formFile').submit(); – Daniel Feb 06 '15 at 20:02
  • 1
    Also it didn't work for me. I've created dynamic form, and triggered submit, but after, when I've got the answer from ajax, listener with ajax:complete does't triggered. – fdrv Oct 07 '15 at 11:39
  • @JamaicaGeek - thank you - do you know how i can succeed binding to a dynamically generated form? – BKSpurgeon Aug 15 '16 at 06:19
  • @BKSpurgeon - This wont work for a dynamically generated form as it is. You will need to use something like http://api.jquery.com/live/ or http://api.jquery.com/on/ to cater to dynamic elements. – geeky_monster Aug 18 '16 at 19:53
  • 1
    If this isn't working for you, such as in the case of dynamically generated form the solution should be to bind the listener to the document instead like this: `$(document).bind('ajax:complete', "#my-form", function() { this.doesFoo(); }); – MCB Mar 16 '17 at 02:35
  • got curious how this got that much upvotes, as it doesn't apply to normal forms (sent with a submit button). The answer by Bradley is more complete and explains how this one could "work" (if you didn't include a success callback, what makes no sense at all). – igorsantos07 Oct 02 '18 at 18:08
37

I could not get the number one upvoted solution to work reliably, but have found this works. Not sure if it's required or not, but I do not have an action or method attribute on the tag, which ensures the POST is handled by the $.ajax function and gives you the callback option.

<form id="form">
...
<button type="submit"></button>
</form>

<script>
$(document).ready(function() {
  $("#form_selector").submit(function() {

    $.ajax({
     type: "POST",
      url: "form_handler.php",
      data: $(this).serialize(),
      success: function() {
        // callback code here
       }
    })

  })
})
</script>
Bradley Bossard
  • 2,259
  • 2
  • 21
  • 27
  • 1
    +1. The key to this answer is the `$(this).serialize()` line. It lets you use `jQuery.ajax()` to submit the existing form in the background, then catch the reply from the server and do something with it. – Warren Young Apr 09 '14 at 19:15
  • 18
    javascript without semicolons... some people just want to watch the world burn. Your solution works though, so thanks :) – viggity Jul 16 '14 at 15:45
  • 2
    Note that `.serialize` doesn't include file inputs in your POSTed request. Use the HTML5 FormData (see [this question](http://stackoverflow.com/q/10899384/957950)) instead unless you are supporting old browsers like IE < 9 – brichins Nov 09 '15 at 20:26
  • Props for using `$(this).serialize()`, it solved my problems! – gnclmorais Jun 29 '16 at 10:13
  • what is 'form_selector' in your html that you reference in the js? – Kevin Meredith Jul 25 '16 at 15:08
  • @KevinMeredith it's the id of the form... Same thing as "#myform" in the original posting. – Bradley Bossard Jul 25 '16 at 18:59
  • Actually [Eslint](http://eslint.org/docs/rules/no-extra-semi) suggest to not use unnecessary semicolons, and it won't burn the world :) @viggity. The solution works perfectly for me, thanks. – wenwen Sep 27 '16 at 06:52
  • @wenwen That lint rule is for *extra* semi-colon. It does not discourage the use of them, it just says don't use two when one is enough. I for one agree with viggity, not using them will make the world burn, or at least your code when someone accidentally removes a line break. – Carl Sep 19 '17 at 10:23
23

You'll have to do things manually with an AJAX call to the server. This will require you to override the form as well.

But don't worry, it's a piece of cake. Here's an overview on how you'll go about working with your form:

  • override the default submit action (thanks to the passed in event object, that has a preventDefault method)
  • grab all necessary values from the form
  • fire off an HTTP request
  • handle the response to the request

First, you'll have to cancel the form submit action like so:

$("#myform").submit(function(event) {
    // Cancels the form's submit action.
    event.preventDefault();
});

And then, grab the value of the data. Let's just assume you have one text box.

$("#myform").submit(function(event) {
    event.preventDefault();
    var val = $(this).find('input[type="text"]').val();
});

And then fire off a request. Let's just assume it's a POST request.

$("#myform").submit(function(event) {
    event.preventDefault();
    var val = $(this).find('input[type="text"]').val();

    // I like to use defers :)
    deferred = $.post("http://somewhere.com", { val: val });

    deferred.success(function () {
        // Do your stuff.
    });

    deferred.error(function () {
        // Handle any errors here.
    });
});

And this should about do it.

Note 2: For parsing the form's data, it's preferable that you use a plugin. It will make your life really easy, as well as provide a nice semantic that mimics an actual form submit action.

Note 2: You don't have to use defers. It's just a personal preference. You can equally do the following, and it should work, too.

$.post("http://somewhere.com", { val: val }, function () {
    // Start partying here.
}, function () {
    // Handle the bad news here.
});
Sal Rahman
  • 4,228
  • 2
  • 27
  • 39
10

For MVC here was an even easier approach. You need to use the Ajax form and set the AjaxOptions

@using (Ajax.BeginForm("UploadTrainingMedia", "CreateTest", new AjaxOptions() { HttpMethod = "POST", OnComplete = "displayUploadMediaMsg" }, new { enctype = "multipart/form-data", id = "frmUploadTrainingMedia" }))
{ 
  ... html for form
}

here is the submission code, this is in the document ready section and ties the onclick event of the button to to submit the form

$("#btnSubmitFileUpload").click(function(e){
        e.preventDefault();
        $("#frmUploadTrainingMedia").submit();
});

here is the callback referenced in the AjaxOptions

function displayUploadMediaMsg(d){
    var rslt = $.parseJSON(d.responseText);
    if (rslt.statusCode == 200){
        $().toastmessage("showSuccessToast", rslt.status);
    }
    else{
        $().toastmessage("showErrorToast", rslt.status);
    }
}

in the controller method for MVC it looks like this

[HttpPost]
[ValidateAntiForgeryToken]
public JsonResult UploadTrainingMedia(IEnumerable<HttpPostedFileBase> files)
{
    if (files != null)
    {
        foreach (var file in files)
        {
            // there is only one file  ... do something with it
        }
        return Json(new
        {
            statusCode = 200,
            status = "File uploaded",
            file = "",
        }, "text/html");
    }
    else
    {
        return Json(new
        {
            statusCode = 400,
            status = "Unable to upload file",
            file = "",
        }, "text/html");
    }
}
edepperson
  • 1,017
  • 1
  • 13
  • 31
  • 2
    Those code are .Net codes, and in the question never specified it. – MrMins Oct 01 '14 at 07:18
  • 13
    That really isn't a good reason for down voting this. The answer works and might help a .NET developer who is facing the same issue. – edepperson Oct 02 '14 at 13:44
  • I like this idea, but for some reason the callback isn't firing. Does the controller method have to return a JsonResult? My controller method currently returns an ActionResult. – mattpm Sep 17 '19 at 01:29
7

I do not believe there is a callback-function like the one you describe.

What is normal here is to do the alterations using some server-side language, like PHP.

In PHP you could for instance fetch a hidden field from your form and do some changes if it is present.

PHP:

  $someHiddenVar = $_POST["hidden_field"];
    if (!empty($someHiddenVar)) {
        // do something 
    }

One way to go about it in Jquery is to use Ajax. You could listen to submit, return false to cancel its default behaviour and use jQuery.post() instead. jQuery.post has a success-callback.

$.post("test.php", $("#testform").serialize(), function(data) {
  $('.result').html(data);
});

http://api.jquery.com/jQuery.post/

Sindre
  • 3,780
  • 2
  • 24
  • 39
0

The form's "on submit" handlers are called before the form is submitted. I don't know if there is a handler to be called after the form is submited. In the traditional non-Javascript sense the form submission will reload the page.

eel ghEEz
  • 1,007
  • 10
  • 23
  • Unless the form submission redirects to a file download, in which case the page is left intact. I can't use JavaScript submission because an Ajax request can't initiate a file download (without anchor tag games), but I also can't tell the user to wait, or clean up once they have the file... – kitsu.eb Aug 29 '19 at 19:24
-1
$("#formid").ajaxForm({ success: function(){ //to do after submit } });
Aikanáro
  • 833
  • 3
  • 17
  • 39