76

I have a form that looks like this

<form action="receiver.pl" method="post">
  <input name="signed" type="checkbox">
  <input value="Save" type="submit">
</form>

and I would like to stay on the same page, when Submit is clicked, but still have receiver.pl executed.

How should that be done?

Sandra Schlichting
  • 25,050
  • 33
  • 110
  • 162

5 Answers5

91

99% of the time I would use XMLHttpRequest or fetch for something like this. However, there's an alternative solution which doesn't require javascript...

You could include a hidden iframe on your page and set the target attribute of your form to point to that iframe.

<style>
  .hide { position:absolute; top:-1px; left:-1px; width:1px; height:1px; }
</style>

<iframe name="hiddenFrame" class="hide"></iframe>

<form action="receiver.pl" method="post" target="hiddenFrame">
  <input name="signed" type="checkbox">
  <input value="Save" type="submit">
</form>

There are very few scenarios where I would choose this route. Generally handling it with javascript is better because, with javascript you can...

  • gracefully handle errors (e.g. retry)
  • provide UI indicators (e.g. loading, processing, success, failure)
  • run logic before the request is sent, or run logic after the response is received.
jessegavin
  • 74,067
  • 28
  • 136
  • 164
  • 4
    Didn't say that this was the best answer out there. Just another option. ;) – jessegavin Apr 20 '11 at 23:56
  • 2
    This actually may be the best answer here... You don't have to use Jquery, Ajax etc – spauny Oct 04 '12 at 09:40
  • I am also struck in a similar situation and tried what @jessegavin suggested. But upon submission the perl cgi is not fetching the form elements. Any suggestions? – Govind Kailas Jan 23 '14 at 20:10
  • Btwn - the fields/form elements are being populated by jQuery datepicker – Govind Kailas Jan 23 '14 at 20:13
  • 1
    @GovindKailas Maybe you should post your own StackOverflow question because it's probably not directly related to this one. However, double check that all your fields have a `name` attribute. – jessegavin Jan 23 '14 at 20:44
  • Yeah, I just got one here http://stackoverflow.com/questions/21319469/jquery-elements-not-getting-passed-to-perl-cgi @jessegavin – Govind Kailas Jan 23 '14 at 21:16
  • 1
    I like this one because it is the most simple, doesnt require additional libraries and just uses html. I was exactly what I was looking for. – contractorwolf Jan 28 '14 at 00:39
70

The easiest answer: jQuery. Do something like this:

$(document).ready(function(){
   var $form = $('form');
   $form.submit(function(){
      $.post($(this).attr('action'), $(this).serialize(), function(response){
            // do something here on success
      },'json');
      return false;
   });
});

If you want to add content dynamically and still need it to work, and also with more than one form, you can do this:

   $('form').live('submit', function(){
      $.post($(this).attr('action'), $(this).serialize(), function(response){
            // do something here on success
      },'json');
      return false;
   });
Riley Lark
  • 20,660
  • 15
  • 80
  • 128
Herman Schaaf
  • 46,821
  • 21
  • 100
  • 139
  • This looks very interesting! How do I tell it to execute the `receiver.pl` script? – Sandra Schlichting Apr 20 '11 at 17:14
  • the part where it says '$form.attr('action')' does that - it tells jQuery's submit function to call the action specified by the form ('receiver.pl'), without leaving the page, i.e. using AJAX. – Herman Schaaf Apr 20 '11 at 17:57
  • I must be doing something wrong then, because it still changes page to `receiver.pl` I have added your code to the header section, and included ``. Do I need to make other changes? – Sandra Schlichting Apr 20 '11 at 18:06
  • Btw. I have found this page, http://www.askaboutphp.com/213/php-and-jquery-submit-a-form-without-refreshing-the-page.html , but I can't quite understand it. – Sandra Schlichting Apr 20 '11 at 18:09
  • Hi, sorry, I had a mistake in my code - should have tested it. It's important to `return false;` at the end. Also, if the page returns an error in the javascript, the form will submit in the default way. That might be why it's still loading the new page. – Herman Schaaf Apr 20 '11 at 18:11
  • Btw. It seams that this only works on the first form on the page. Can it be modified, so it works on all forms on the page? – Sandra Schlichting Apr 20 '11 at 18:25
  • This should work on all forms on the page - unless the forms are loaded after the rest of the page was loaded, which I presume it isn't. – Herman Schaaf Apr 20 '11 at 18:26
  • I guess that's the problem then. I have written the page in Perl using `CGI::Application` and `HTML::Template`, where I only define one form, it is copied many times... Do you have an idea how that be worked around? – Sandra Schlichting Apr 20 '11 at 18:38
  • Well, that still shouldn't be a problem then - are you sure it doesn't work? Are the other forms valid? If you want, you could try replacing `$form.submit(function(){` with `$form.live('submit',function(){` but I doubt that will solve your problem. In all probability, it's related to something else. If you do that, you should also remove the first and last lines of my example code. – Herman Schaaf Apr 20 '11 at 18:40
  • @Herman, your JQuery code looks like it's finding the first form on the page and altering how it is submited, you need to modify it to find all forms and loop through and modify them all. – Ven'Tatsu Apr 20 '11 at 18:53
  • @Ven'Tatsu: no, the code selects everything with a `form` tag, and then applies the `submit` function to each of the selected elements. Test it yourself on a selection for all

    tags `$(p).css('background', '#f00');` - that will make all paragraphs have a red background, not just the first one.

    – Herman Schaaf Apr 20 '11 at 19:02
  • @Herman. If I make that change, then it doesn't stay on the same page. Here is the HTML template, where I have pasted your code in. http://pastebin.com/ERMqkPVF – Sandra Schlichting Apr 20 '11 at 19:16
  • @Sandra: It doesn't reload the page when I click save, seems to work with me - something else might be causing a javascript error, and that might cause the page to reload. – Herman Schaaf Apr 20 '11 at 19:20
  • That is correct with the version of your code from the accepted answer, but making the `$form.live('submit',function(){` change does. – Sandra Schlichting Apr 20 '11 at 19:23
  • Hi, I updated my answer just to make sure we're understanding each other correctly. – Herman Schaaf Apr 20 '11 at 19:32
  • Damn! You are good! Now it works for all forms =) So the problem was that, JavaScript is executed before `HTML::Template` is done render the HTML? – Sandra Schlichting Apr 20 '11 at 19:52
  • No, both code snippets in my answer should work in your case (as far as I know) - it might just have been something small - I don't know why it didn't work in the first place. But I'm glad if it works now :) – Herman Schaaf Apr 20 '11 at 19:57
  • Me too =) I got to find a good JQuery book, and learn this awesome library! http://www.learningjquery.com/ seams popular. – Sandra Schlichting Apr 20 '11 at 20:01
  • Sorry, can't help you there, I learnt all I know from the jQuery documentation ;) but take a look at this thread, http://stackoverflow.com/q/96818/445210 - seems most people recommend jQuery in Action – Herman Schaaf Apr 20 '11 at 20:04
  • JQuery in Action is cheaper. I think we have a winner =) – Sandra Schlichting Apr 20 '11 at 20:11
  • Very nice. Unfortunately if you use a button inside your form its value will not be sent along..:( – Vincent Ketelaars Jan 18 '14 at 21:25
  • Do you know if this will submit multipart forms correctly? I have a feeling it won't but could someone confirm? – Josh Feb 03 '14 at 08:57
  • @Josh No, but you can see how to do it in [this question](http://stackoverflow.com/questions/166221/how-can-i-upload-files-asynchronously-with-jquery) and also [here](http://digipiph.com/blog/submitting-multipartform-data-using-jquery-and-ajax). – Herman Schaaf Feb 03 '14 at 09:23
  • will it handle multi type form datas? i mean,will it work on input type file submit? – Kvvaradha Mar 19 '16 at 08:45
  • 1
    @Kvvaradha No, to handle file uploads you will need to send that explicitly with jquery's `data` parameter to the `$.ajax` function, `new FormData($(this)[0]);` and add `enctype="multipart/form-data"` to the form. See this answer: http://stackoverflow.com/a/10899796/445210 – Herman Schaaf Mar 19 '16 at 10:00
44

The HTTP/CGI way to do this would be for your program to return an HTTP status code of 204 (No Content).

Ciro Santilli OurBigBook.com
  • 347,512
  • 102
  • 1,199
  • 985
Dave Cross
  • 68,119
  • 3
  • 51
  • 97
  • 4
    Super cool! Learned something new today. Howerver, in practical terms, you would really want to provide the user with some sort of visual feedback that the form submission was processed by the server. It doesn't seem that browsers provide that out of the box, so using AJAX to interpret the HTTP 204 would probably be the best bet. – jessegavin May 28 '13 at 16:36
  • Wow... Thanks!... This is really an amazing tip, It doesn't exactly 100% solve the problem I'm having but it's definitely an temporary solution. Thanks so much! – Ilan Kleiman Feb 05 '14 at 01:36
  • This is great. Thanks! – Sean Anderson Jan 30 '16 at 21:12
  • A simple and great way of doing it in simple html. Great! – Kiran Sep 18 '16 at 06:57
  • That is such a nice way to do it. Much simpler than other approaches. – Andrew Jan 03 '17 at 12:12
2

Use XMLHttpRequest

var xhr = new XMLHttpRequest();
xhr.open("POST", '/server', true);

//Send the proper header information along with the request
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");

xhr.onreadystatechange = function() { // Call a function when the state changes.
    if (this.readyState === XMLHttpRequest.DONE && this.status === 200) {
        // Request finished. Do processing here.
    }
}
xhr.send("foo=bar&lorem=ipsum");
// xhr.send(new Int8Array()); 
// xhr.send(document);
Hasan A Yousef
  • 22,789
  • 24
  • 132
  • 203
2

When you hit on the submit button, the page is sent to the server. If you want to send it async, you can do it with ajax.

Paritosh
  • 1,111
  • 1
  • 12
  • 29
Eric Frick
  • 847
  • 1
  • 7
  • 18