XMLHttpRequest to Post HTML Form
Asked Answered
A

6

25

Current Setup

I have an HTML form like so.

<form id="demo-form" action="post-handler.php" method="POST">
   <input type="text" name="name" value="previousValue"/>
   <button type="submit" name="action" value="dosomething">Update</button>
</form>

I may have many of these forms on a page.

My Question

How do I submit this form asynchronously and not get redirected or refresh the page? I know how to use XMLHttpRequest. The issue I have is retrieving the data from the HTML in javascript to then put into a post request string. Here is the method I'm currently using for my zXMLHttpRequest`'s.

function getHttpRequest() {
    var xmlhttp;
    if (window.XMLHttpRequest) {// code for IE7+, Firefox, Chrome, Opera, Safari
        xmlhttp=new XMLHttpRequest();
    } else {// code for IE6, IE5
        xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
    }
    
    return xmlhttp;
}

function demoRequest() {
       var request = getHttpRequest();
       request.onreadystatechange=function() {
             if (request.readyState == 4 && request.status == 200) {
                   console.log("Response Received");
             }
       }
       request.open("POST","post-handler.php",true);
       request.setRequestHeader("Content-type","application/x-www-form-urlencoded");
       request.send("action=dosomething");
}

So for example, say the javascript method demoRequest() was called when the form's submit button was clicked, how do I access the form's values from this method to then add it to the XMLHttpRequest?

EDIT

Trying to implement a solution from an answer below I have modified my form like so.

<form id="demo-form">
       <input type="text" name="name" value="previousValue"/>
       <button type="submit" name="action" value="dosomething" onClick="demoRequest()">Update</button>
</form>

However, on clicking the button, it's still trying to redirect me (to where I'm unsure) and my method isn't called?

Button Event Listener

document.getElementById('updateBtn').addEventListener('click', function (evt) {
                                evt.preventDefault();
                                
                                // Do something
                                updateProperties();
                                
                                return false;
                            });
Acclaim answered 3/9, 2013 at 12:44 Comment(6)
You tagged jQuery but there is no jQuery code... Do you want to use jQuery or pure javascript ?Eiten
Sorry misclick. Just javascriptAcclaim
I posted an answer that you can use via jquery thoughNatatorial
possible duplicate of Sending POST data with a XMLHttpRequestEigenfunction
To prevent the default form action, set an event listener on the form's submit event, instead of the button's click event. (And still call evt.preventDefault();)Nog
In your edit captioned "Button Event Listener", where exactly would you put that code? into the functions demoRequest() body? why the return false statement?Bocage
I
37

The POST string format is the following:

name=value&name2=value2&name3=value3

So you have to grab all names, their values and put them into that format. You can either iterate all input elements or get specific ones by calling `document.getElementById()`.

Warning: You have to use encodeURIComponent() for all names and especially for the values so that possible & contained in the strings do not break the format.

Example:

var input = document.getElementById("my-input-id");
var inputData = encodeURIComponent(input.value);

request.send("action=dosomething&" + input.name + "=" + inputData);

Another far simpler option would be to use FormData objects. Such an object can hold name and value pairs.

Luckily, we can construct a FormData object from an existing form and we can send it it directly to XMLHttpRequest's method send():

var formData = new FormData( document.getElementById("my-form-id") );
xhr.send(formData);
Idem answered 3/9, 2013 at 12:53 Comment(12)
Do I override the button's onClick function and point it to my XMLHttpRequest method?Acclaim
@DiscoS2 Yes. Do you have any other event handlers registered for the click event?Idem
Not for this form no.Acclaim
Thank you for expanding on your answer more. I am having issues submitting the form. I have remove the action and method from the <form> tag as it was still posting via HTML. How do I call my javascript method?Acclaim
@DiscoS2 How did you assign the event listener? Can you show us the code (in your answer - not in a comment, please)?Idem
Added the code in my original question. However, its not a listener... unsure of how to do this?Acclaim
@DiscoS2 Try this code: jsfiddle.net/ZsHgu (add an ID to your button and register an event listener as provided in the fiddle).Idem
let us continue this discussion in chatAcclaim
Your code does not work with file uploads... I used var formData = new FormData( document.getElementById("my-form-id") ); and formData is empty.Civic
@Civic According to MDN on FormData objects, it should work. Did you use a POST or GET request?Idem
@ComFreek, It works now. It was not working because of a wrong header (#50021148)Civic
This doesn't work in an addon. how to do this without overriding the onsubmit()? addons/extensions do not allow overriding onsubmit due to security reasons.Aviation
E
19

The ComFreek's answer is correct but a complete example is missing.

Therefore I have wrote an extremely simplified working snippet:

<!DOCTYPE html>
<html>
<head>
<meta http-equiv="X-UA-Compatible" content="IE=Edge, chrome=1"/>

<script>
"use strict";
function submitForm(oFormElement)
{
  var xhr = new XMLHttpRequest();
  xhr.onload = function(){ alert(xhr.responseText); }
  xhr.open(oFormElement.method, oFormElement.getAttribute("action"));
  xhr.send(new FormData(oFormElement));
  return false;
}
</script>
</head>

<body>
<form method="POST"
      action="post-handler.php"
      onsubmit="return submitForm(this);" >
   <input type="text"   value="previousValue" name="name"/>
   <input type="submit" value="Update"/>
</form>
</body>
</html>

This snippet is basic and cannot use GET. I have been inspired from the excellent Mozilla Documentation. Have a deeper read of this MDN documentation to do more. See also this answer using formAction.

Eigenfunction answered 7/11, 2013 at 13:14 Comment(6)
When I use this method my form is submitting multiple(2) times. Any suggestion?Sulfate
Today I just found a small fix for this. I have changed onsubmit="submitForm(this);" to onsubmit="return submitForm(this);". Rest of your code remains same. This solved my problem. Thanks.Sulfate
Thank you @MayurPatel very much for your feedback. I have just edited the snippet to reflect your contribution. Have fun ;-)Eigenfunction
You should use oFormElement.getAttribute("action") in case you ever add an input field named "action", which will override your oFormElement.action. Same goes for method ofcMillymilman
Thank you @Millymilman for your advice 👍 I have just applied your trick. Should I do the same for oFormElement.getAttribute("method")? I am a bit afraid my original tiny snippet is becoming more complex... What do you think? Have fun 😊Eigenfunction
@olibre Async is by default true, so you don't need it - developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/…Crocodile
J
4

By the way I have used the following code to submit form in ajax request.

 $('form[id=demo-form]').submit(function (event) {

    if (request) {
        request.abort();
    }
    // setup some local variables
    var $form = $(this);

    // let's select and cache all the fields
    var $inputs = $form.find("input, select, button, textarea");


    // serialize the data in the form
    var serializedData = $form.serialize();


    // fire off the request to specific url

    var request = $.ajax({
        url : "URL TO POST FORM",
        type: "post",
        data: serializedData
    });
    // callback handler that will be called on success
    request.done(function (response, textStatus, jqXHR){


    });

    // callback handler that will be called on failure
    request.fail(function (jqXHR, textStatus, errorThrown){

    });

    // callback handler that will be called regardless
    // if the request failed or succeeded
    request.always(function () {
        // reenable the inputs

    });

    // prevent default posting of form
    event.preventDefault();
});
Jenifferjenilee answered 3/9, 2013 at 12:50 Comment(4)
The OP does not want to use jQuery.Idem
@Idem He didn't mention in question. Now he mentioned in comment. I posted answer before this comment.Jenifferjenilee
Thanks for posting Awais, I found this thread and I DO want to use jQueryPasto
If we wanted ajax we would have used jq so no thanksFries
F
0

With pure Javascript, you just want something like:

var val = document.getElementById("inputFieldID").value;

You want to compose a data object that has key-value pairs, kind of like

name=John&lastName=Smith&age=3

Then send it with request.send("name=John&lastName=Smith&age=3");

Felipa answered 3/9, 2013 at 12:57 Comment(0)
H
0

I have had this problem too, I think.

I have a input element with a button. The onclick method of the button uses XMLHttpRequest to POST a request to the server, all coded in the JavaScript.

When I wrapped the input and the button in a form the form's action property was used. The button was not type=submit which form my reading of HTML standard (https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#attributes-for-form-submission) it should be.

But I solved it by overriding the form.onsubmit method like so:

form.onsubmit = function(E){return false;}

I was using FireFox developer edition and chromium 38.0.2125.111 Ubuntu 14.04 (290379) (64-bit).

Hux answered 4/12, 2014 at 23:35 Comment(0)
W
-1
function postt(){
    var http = new XMLHttpRequest();
    var y = document.getElementById("user").value;
    var z = document.getElementById("pass").value;
    var postdata= "username=y&password=z"; //Probably need the escape method for values here, like you did

    http.open("POST", "chat.php", true);

    //Send the proper header information along with the request
    http.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
    http.setRequestHeader("Content-length", postdata.length);

    http.onreadystatechange = function() {//Call a function when the state changes.
        if(http.readyState == 4 && http.status == 200) {
            alert(http.responseText);
        }
    }
    http.send(postdata);
}

how can I post the values of y and z here from the form

Warring answered 25/1, 2017 at 9:26 Comment(1)
If you have a separate question, you should create one rather than posting an answer on an already existing question. Thank you.Supremacy

© 2022 - 2024 — McMap. All rights reserved.