0

I have the following form and javascript function on my web page. This is a dummy function that I am using to test whether what I would like to do is possible.

What I am attempting to do is have a form send an AJAX request to the server, so that the server can update the database while the page itself continues along it's predetermined path. I am in a tight time crunch, so I unfortunately do not have time to rewrite the entire page to better support this. The problem that I have is the xmlhttp object does not seem to return properly. I get a readyState of 4 but a status of 0. can someone please explain what I need to do?

Here's my code:

ajax.php

<html>
<head>
<script type="text/javascript">
function test(){
    var xmlhttp = new XMLHttpRequest();

    xmlhttp.onreadystatechange=function(){
        document.getElementById("new").innerHTML+="<b>"+xmlhttp.readyState+"</b> "+xmlhttp.status;

        if (xmlhttp.readyState==4 && xmlhttp.status==200){
            document.getElementById("hello").innerHTML=xmlhttp.responseText;
        }
    }

    xmlhttp.open("GET","response.php",true);
    xmlhttp.send();
}
</script>
</head>

<body>
<?php
if ($_POST){
  echo $_POST['hello'];
}
?>

<form action="ajax.php" method="post">
<input type="text" name="hello" />
<input type="submit" value="submit" onclick="test();" />
</form>

<div id="hello"></div>
<h3>debug</h3>
<div id="new"></div>
</body>
</html>

response.php

<?php
echo "Hello there";
?>

EDIT

Please note that I do not want to prevent the default behavior. In fact, the forn must be submitted as usual. I simply want to add an AJAX request to the process.

ewok
  • 20,148
  • 51
  • 149
  • 254
  • http://stackoverflow.com/questions/5081674/jquery-prevent-default-browser-form-submit-behaviour-but-submit-form-with-jquer – check123 Jan 13 '12 at 14:16
  • http://stackoverflow.com/questions/1357118/javascript-event-preventdefault-vs-return-false – check123 Jan 13 '12 at 14:17
  • @check123 please not that I do NOT want to prevent the default behavior. The form needs to be submitted as it normally would, but I want the AJAX request to happen as well. – ewok Jan 13 '12 at 14:18
  • If you want both then let the default action happen and use javascript `event listener` for the form submit and trigger the ajax function onsubmit. http://help.dottoro.com/ljeuqqoq.php – check123 Jan 13 '12 at 14:21
  • @check123 can you provide and example and submit it as an answer? – ewok Jan 13 '12 at 14:28
  • What if you change `` to ``? Look here: http://stackoverflow.com/questions/3348605/different-behavior-of-xmlhttprequest-for-input-type-button-vs-button – BartekR Jan 13 '12 at 14:28
  • 1
    Incomplete AJAX requests are cancelled when the page reloads, which will happen when you submit your form. You'll either have to **not** submit the form at all or submit it once the AJAX request has completed. – Anthony Grist Jan 13 '12 at 14:30
  • @BartekR `` will not submit the form as needed. – ewok Jan 13 '12 at 14:31
  • @AnthonyGrist How do I prevent the page from reloading until after the ajax request has completed? – ewok Jan 13 '12 at 14:32
  • @ewok Moved my initial comment into an answer, and provided slightly modified code that should do what you need. – Anthony Grist Jan 13 '12 at 14:41

3 Answers3

2

I know this doesn't directly answer your question but if you are strapped for time then I would suggest just using jQuery to handle the AJax.

You can attach it to a button press and then call some code: http://api.jquery.com/jQuery.ajax/

I can dig out some code examples if you need them.

webnoob
  • 15,747
  • 13
  • 83
  • 165
2

You can't trigger an AJAX request and allow the form to submit at the same time. Incomplete AJAX requests are cancelled when the page reloads (as is the case when the form is submitted). You'll either have to not submit the form at all, or wait until your AJAX call has completed before submitting the form. If you wanted to go the second route, you could make the following changes to your code:

<html>
<head>
<script type="text/javascript">
function test(){
    var xmlhttp = new XMLHttpRequest();

    xmlhttp.onreadystatechange=function(){
        document.getElementById("new").innerHTML+="<b>"+xmlhttp.readyState+"</b> "+xmlhttp.status;

        if (xmlhttp.readyState==4 && xmlhttp.status==200){
            document.getElementById("hello").innerHTML=xmlhttp.responseText;
            **document.getElementById("ajaxform").submit();**
        }
    }

    xmlhttp.open("GET","response.php",true);
    xmlhttp.send();
}
</script>
</head>

<body>
<?php
if ($_POST){
  echo $_POST['hello'];
}
?>

<form action="ajax.php" method="post" **id="ajaxform"**>
<input type="text" name="hello" />
<input type="submit" value="submit" onclick="test();**return false;**" />
</form>

<div id="hello"></div>
<h3>debug</h3>
<div id="new"></div>
</body>
</html>

Changes/additions are marked with **.

Note that there are a few practices in there I don't like, in particular using the onsubmit, etc attributes of HTML tags to attach Javascript event handlers.

Anthony Grist
  • 38,173
  • 8
  • 62
  • 76
  • Thanks, this works. Another possible thing that may pop up is whether this can be done with multiple submit buttons? – ewok Jan 13 '12 at 14:49
  • @ewok If they're all in the same form, you want them all to perform the same AJAX call, and you only expect the user to ever click one of them at any given time to submit the form, it will work fine if you just include the `onsubmit="test();return false;` code on each of the HTML tags. If you want the AJAX calls to be unique to each button (ie. one button posts to a different URL/submits different data to another), you'd need to write individual functions for each button. – Anthony Grist Jan 13 '12 at 14:57
  • The way it would be set up is there would be one button that posts changes to the page (an "apply" button) and activates another button that commits the changes to the DB (a "commit" button). What I wonder is when you call `document.getElementById("ajaxform").submit();`, which button will it recognize as aving been clicked? – ewok Jan 13 '12 at 15:09
  • @ewok That makes more sense than what I originally thought you meant. To answer the question: The form passes back the value of the submit button that was clicked on to submit the form; in the case of submitting the form programmatically using Javascript, that's none of them, so no value is passed back. If you have server-side code to determine the button click, you'll need another way to pass that value back (possibly using a hidden form element), or you could simulate clicking on a specific submit button using Javascript rather than submitting the form. – Anthony Grist Jan 13 '12 at 15:16
  • so to set it using a hidden field, could I add `` to the form, then `document.getElementById('button').innerHTML="commit";` to the ajax function and change the check on which button was pressed? – ewok Jan 13 '12 at 15:23
  • Use `value` rather than `innerHTML` to set the value of the hidden input element, but otherwise that's correct. – Anthony Grist Jan 13 '12 at 15:26
0

Once the submit button is pressed the browser will submit data to the server and a new page will be loaded. You can bind the submit event of the form and in the event make the ajax call but you will have 2 problems.

  1. The browser may redirect before all ajax data is sent
  2. You have no idea if the ajax call was successful or not

I would try sending the data you are sending via ajax in the same form data using hidden inputs. If both calls are aimed at different urls then try this:

var ajaxSent = false;
$('#myForm').submit(function(e){
    if (!ajaxSent){
        e.preventDefault();
        $.ajax({
            url: "ajaxUrl",
            // data, method, etc
            success: function(){
                ajaxSent = true;
                $('#myForm').trigger('submit');
            }
    }
    // else submit the form
});
Juank
  • 6,096
  • 1
  • 28
  • 28
  • While I prefer to use jQuery myself the code in the question is in regular Javascript and there's no jQuery tag, or any mention of it in the question. You should at the least point out in your answer that the code uses jQuery, possibly with a link to the jQuery site. – Anthony Grist Jan 13 '12 at 14:45
  • Downvote as no reference is made to this using jQuery and the OP wasn't originally. – webnoob Jan 13 '12 at 15:27