1764

I'm trying to direct a browser to a different page. If I wanted a GET request, I might say

document.location.href = 'http://example.com/q=a';

But the resource I'm trying to access won't respond properly unless I use a POST request. If this were not dynamically generated, I might use the HTML

<form action="http://example.com/" method="POST">
    <input type="hidden" name="q" value="a">
</form>

Then I would just submit the form from the DOM.

But really I would like JavaScript code that allows me to say

post_to_url('http://example.com/', {'q':'a'});

What's the best cross browser implementation?

I need a solution that changes the location of the browser, just like submitting a form. If this is possible with XMLHttpRequest, it is not obvious. And this should not be asynchronous, nor use XML, so Ajax is not the answer.

2
  • 2
    As mentioned in another thread there is a jquery ".redirect" plugin that works with the POST or GET method. It creates a form with hidden inputs and submits it for you. Ex: $.redirect('demo.php', {'arg1': 'value1', 'arg2': 'value2'}); github.com/mgalante/jquery.redirect/blob/master/…
    – OG Sean
    Commented Jul 9, 2018 at 0:16
  • The document object doesn't have a location.href you need a to use window.
    – Justin Liu
    Commented Jun 12, 2020 at 15:07

32 Answers 32

2386

Dynamically create <input>s in a form and submit it

/**
 * sends a request to the specified url from a form. this will change the window location.
 * @param {string} path the path to send the post request to
 * @param {object} params the parameters to add to the url
 * @param {string} [method=post] the method to use on the form
 */

function post(path, params, method='post') {

  // The rest of this code assumes you are not using a library.
  // It can be made less verbose if you use one.
  const form = document.createElement('form');
  form.method = method;
  form.action = path;

  for (const key in params) {
    if (params.hasOwnProperty(key)) {
      const hiddenField = document.createElement('input');
      hiddenField.type = 'hidden';
      hiddenField.name = key;
      hiddenField.value = params[key];

      form.appendChild(hiddenField);
    }
  }

  document.body.appendChild(form);
  form.submit();
}

Example:

post('/contact/', {name: 'Johnny Bravo'});

EDIT: Since this has gotten upvoted so much, I'm guessing people will be copy-pasting this a lot. So I added the hasOwnProperty check to fix any inadvertent bugs.

23
  • 14
    What about arrays in data params? Jquery post() interprets e.g.: "data: {array: [1, 2, 3]}" as ?array=1&array=2&array=3. Whis code gives another result.
    – Scit
    Commented Oct 14, 2015 at 6:36
  • 29
    Warning: Despite the many upvotes, this solution is limited and does not handle arrays or nested objects inside of a form. Otherwise it's a great answer.
    – emragins
    Commented Oct 20, 2015 at 16:41
  • 7
    amazing this is not natively supported either by html nor javascript not jquery .. you have to code this.
    – eugene
    Commented Feb 17, 2016 at 8:02
  • 17
    @mricci The point of this snippet is to redirect the browser to a new URL specified by the action; if you're staying on the same page you can just use traditional AJAX to POST your data. Since the browser should be navigating to a new page, the current page's DOM's contents won't matter Commented Jul 7, 2016 at 13:07
  • 8
    Python, Django and probably Flask users will see this error: "Forbidden (403). CSRF verification failed. Request aborted.", if creating a form from zero. In this case, you must pass the csrf token this way: post('/contact/', {name: 'Johnny Bravo', csrfmiddlewaretoken: $("#csrf_token").val()}); Commented Nov 22, 2017 at 16:09
155

This would be a version of the selected answer using jQuery.

// Post to the provided URL with the specified parameters.
function post(path, parameters) {
    var form = $('<form></form>');

    form.attr("method", "post");
    form.attr("action", path);

    $.each(parameters, function(key, value) {
        var field = $('<input></input>');

        field.attr("type", "hidden");
        field.attr("name", key);
        field.attr("value", value);

        form.append(field);
    });

    // The form needs to be a part of the document in
    // order for us to be able to submit it.
    $(document.body).append(form);
    form.submit();
}
3
  • 9
    Slightly modified this to support arrays and objects gist.github.com/hom3chuk/692bf12fe7dac2486212 Commented Sep 28, 2015 at 22:39
  • 4
    If value contains a dangeours xml character, this won't work in ASP.NET encodeUriComponent(value) is required. Then, UrlDecode is also required on the server-side. Commented Mar 13, 2018 at 16:26
  • 1
    If your needs are simple, then this function is unnecessary. This one-liner is sufficient: $("<form method='POST' action='https://example.com'><input type='hidden' name='q' value='a'/></form>").appendTo("body").submit();
    – rinogo
    Commented Jul 17, 2019 at 19:31
87

A simple quick-and-dirty implementation of @Aaron answer:

document.body.innerHTML += '<form id="dynForm" action="http://example.com/" method="post"><input type="hidden" name="q" value="a"></form>';
document.getElementById("dynForm").submit();

Of course, you should rather use a JavaScript framework such as Prototype or jQuery...

3
  • 6
    Is there a way to do this without there being a web page loaded in the current browser window/tab? Commented Sep 24, 2010 at 20:37
  • How do I insert the csrf here?
    – Shulz
    Commented Sep 20, 2020 at 10:29
  • @Shulz You can add another hidden input with [name] set to the key, and [value] set to the token value. Commented Dec 13, 2020 at 21:40
55

Using the createElement function provided in this answer, which is necessary due to IE's brokenness with the name attribute on elements created normally with document.createElement:

function postToURL(url, values) {
    values = values || {};

    var form = createElement("form", {action: url,
                                      method: "POST",
                                      style: "display: none"});
    for (var property in values) {
        if (values.hasOwnProperty(property)) {
            var value = values[property];
            if (value instanceof Array) {
                for (var i = 0, l = value.length; i < l; i++) {
                    form.appendChild(createElement("input", {type: "hidden",
                                                             name: property,
                                                             value: value[i]}));
                }
            }
            else {
                form.appendChild(createElement("input", {type: "hidden",
                                                         name: property,
                                                         value: value}));
            }
        }
    }
    document.body.appendChild(form);
    form.submit();
    document.body.removeChild(form);
}
4
  • 7
    Do you need to remove the child after submission? Doesn't the page go away anyway?
    – Nils
    Commented May 31, 2012 at 22:31
  • 2
    There is no use to remove the child after submission, except if a session is used and those data are saved. Commented Jul 20, 2012 at 7:07
  • 6
    @CantucciHQ The page might just as well stay unchanged even if form target is not set. There is 204 No Content, for example. Commented Jan 30, 2014 at 11:41
  • Just wonder how can append value (image file in form blob or Base64 and image filename) I got after clicking input button as the to submit through the dunamically created form. Commented Mar 18, 2022 at 5:32
40

Rakesh Pai's answer is amazing, but there is an issue that occurs for me (in Safari) when I try to post a form with a field called submit. For example, post_to_url("http://google.com/",{ submit: "submit" } );. I have patched the function slightly to walk around this variable space collision.

function post_to_url(path, params, method) {
    method = method || "post";

    var form = document.createElement("form");
    
    //Move the submit function to another variable
    //so that it doesn't get overwritten.
    form._submit_function_ = form.submit;
    
    form.setAttribute("method", method);
    form.setAttribute("action", path);

    for(var key in params) {
        var hiddenField = document.createElement("input");
        hiddenField.setAttribute("type", "hidden");
        hiddenField.setAttribute("name", key);
        hiddenField.setAttribute("value", params[key]);

        form.appendChild(hiddenField);
    }

    document.body.appendChild(form);
    form._submit_function_(); //Call the renamed function.
}
post_to_url("http://google.com/", { submit: "submit" } ); //Works!
4
  • 10
    2018 and still not a better answer?
    – iiirxs
    Commented Jun 20, 2018 at 13:35
  • Does Safari still have this issue that needs this workaround?
    – Flimm
    Commented Oct 13, 2020 at 19:48
  • the solution is not working in safari browser and iphone 11 chrome browser/safari browser.. while navigating we are getting "network connection lost". could any one advise on this please. @Flimm , Commented May 25, 2021 at 21:57
  • Wouldnt it be better to store the function locally and then call it? this won't work is someone submits a property named submit_function xD. I havent tested it, but var submitFunction = form.submit; and then submitFunction() should work and have less risk.
    – DGoiko
    Commented Sep 27, 2022 at 19:00
36

No. You can't have the JavaScript post request like a form submit.

What you can have is a form in HTML, then submit it with the JavaScript. (as explained many times on this page).

You can create the HTML yourself, you don't need JavaScript to write the HTML. That would be silly if people suggested that.

<form id="ninja" action="http://example.com/" method="POST">
    <input id="donaldduck" type="hidden" name="q" value="a">
</form>

Your function would just configure the form the way you want it.

function postToURL(a,b,c){
    document.getElementById("ninja").action     = a;
    document.getElementById("donaldduck").name  = b;
    document.getElementById("donaldduck").value = c;
    document.getElementById("ninja").submit();
}

Then, use it like.

postToURL("http://example.com/","q","a");

But I would just leave out the function and just do.

document.getElementById('donaldduck').value = "a";
document.getElementById("ninja").submit();

Finally, the style decision goes in the ccs file.

#ninja { 
    display: none;
}

Personally I think forms should be addressed by name but that is not important right now.

0
32

this is the answer of rakesh, but with support for arrays (which is quite common in forms):

plain javascript:

function post_to_url(path, params, method) {
    method = method || "post"; // Set method to post by default, if not specified.

    // The rest of this code assumes you are not using a library.
    // It can be made less wordy if you use one.
    var form = document.createElement("form");
    form.setAttribute("method", method);
    form.setAttribute("action", path);

    var addField = function( key, value ){
        var hiddenField = document.createElement("input");
        hiddenField.setAttribute("type", "hidden");
        hiddenField.setAttribute("name", key);
        hiddenField.setAttribute("value", value );

        form.appendChild(hiddenField);
    }; 

    for(var key in params) {
        if(params.hasOwnProperty(key)) {
            if( params[key] instanceof Array ){
                for(var i = 0; i < params[key].length; i++){
                    addField( key, params[key][i] )
                }
            }
            else{
                addField( key, params[key] ); 
            }
        }
    }

    document.body.appendChild(form);
    form.submit();
}

oh, and here's the jquery version: (slightly different code, but boils down to the same thing)

function post_to_url(path, params, method) {
    method = method || "post"; // Set method to post by default, if not specified.

    var form = $(document.createElement( "form" ))
        .attr( {"method": method, "action": path} );

    $.each( params, function(key,value){
        $.each( value instanceof Array? value : [value], function(i,val){
            $(document.createElement("input"))
                .attr({ "type": "hidden", "name": key, "value": val })
                .appendTo( form );
        }); 
    } ); 

    form.appendTo( document.body ).submit(); 
}
3
  • 3
    p.s. i now enjoy using that function but instead of submitting the form at the end i simply return it back to the caller. this way i can easily set additional attributes or do other stuff with it if needed. Commented May 26, 2012 at 16:09
  • 4
    Great! very useful. A small change for people who rely on PHP at server side of this form, I changed addField( key, params[key][i] ) to addField(key +'[]', params[key][i]). This makes the $_POST[key] available as array.
    – Thava
    Commented Nov 18, 2013 at 1:07
  • 3
    @Thava you could also set name="bla[]" on your input field. anyways, there are languages other than php that don't support the [] syntax so i'm leaving this unchanged. Commented Nov 18, 2013 at 4:20
27

If you have Prototype installed, you can tighten up the code to generate and submit the hidden form like this:

 var form = new Element('form',
                        {method: 'post', action: 'http://example.com/'});
 form.insert(new Element('input',
                         {name: 'q', value: 'a', type: 'hidden'}));
 $(document.body).insert(form);
 form.submit();
1
  • Aww. I miss Prototype!
    – pdobb
    Commented Aug 20 at 0:52
19

One solution is to generate the form and submit it. One implementation is

function post_to_url(url, params) {
    var form = document.createElement('form');
    form.action = url;
    form.method = 'POST';

    for (var i in params) {
        if (params.hasOwnProperty(i)) {
            var input = document.createElement('input');
            input.type = 'hidden';
            input.name = i;
            input.value = params[i];
            form.appendChild(input);
        }
    }

    form.submit();
}

So I can implement a URL shortening bookmarklet with a simple

javascript:post_to_url('http://is.gd/create.php', {'URL': location.href});
0
17

Well, wish I had read all the other posts so I didn't lose time creating this from Rakesh Pai's answer. Here's a recursive solution that works with arrays and objects. No dependency on jQuery.

Added a segment to handle cases where the entire form should be submitted like an array. (ie. where there's no wrapper object around a list of items)

/**
 * Posts javascript data to a url using form.submit().  
 * Note: Handles json and arrays.
 * @param {string} path - url where the data should be sent.
 * @param {string} data - data as javascript object (JSON).
 * @param {object} options -- optional attributes
 *  { 
 *    {string} method: get/post/put/etc,
 *    {string} arrayName: name to post arraylike data.  Only necessary when root data object is an array.
 *  }
 * @example postToUrl('/UpdateUser', {Order {Id: 1, FirstName: 'Sally'}});
 */
function postToUrl(path, data, options) {
    if (options === undefined) {
        options = {};
    }

    var method = options.method || "post"; // Set method to post by default if not specified.

    var form = document.createElement("form");
    form.setAttribute("method", method);
    form.setAttribute("action", path);

    function constructElements(item, parentString) {
        for (var key in item) {
            if (item.hasOwnProperty(key) && item[key] != null) {
                if (Object.prototype.toString.call(item[key]) === '[object Array]') {
                    for (var i = 0; i < item[key].length; i++) {
                        constructElements(item[key][i], parentString + key + "[" + i + "].");
                    }
                } else if (Object.prototype.toString.call(item[key]) === '[object Object]') {
                    constructElements(item[key], parentString + key + ".");
                } else {
                    var hiddenField = document.createElement("input");
                    hiddenField.setAttribute("type", "hidden");
                    hiddenField.setAttribute("name", parentString + key);
                    hiddenField.setAttribute("value", item[key]);
                    form.appendChild(hiddenField);
                }
            }
        }
    }

    //if the parent 'data' object is an array we need to treat it a little differently
    if (Object.prototype.toString.call(data) === '[object Array]') {
        if (options.arrayName === undefined) console.warn("Posting array-type to url will doubtfully work without an arrayName defined in options.");
        //loop through each array item at the parent level
        for (var i = 0; i < data.length; i++) {
            constructElements(data[i], (options.arrayName || "") + "[" + i + "].");
        }
    } else {
        //otherwise treat it normally
        constructElements(data, "");
    }

    document.body.appendChild(form);
    form.submit();
};
3
  • 1
    This doesn't seem to encode nested objects properly either.
    – mpen
    Commented May 11, 2016 at 18:05
  • 1
    @mpen do you have a fiddle?
    – emragins
    Commented May 11, 2016 at 20:47
  • 1
    No, sorry. It was easy enough to write myself; not worth the time to debug.
    – mpen
    Commented May 11, 2016 at 21:21
14

I'd go down the Ajax route as others suggested with something like:

var xmlHttpReq = false;

var self = this;
// Mozilla/Safari
if (window.XMLHttpRequest) {
    self.xmlHttpReq = new XMLHttpRequest();
}
// IE
else if (window.ActiveXObject) {
    self.xmlHttpReq = new ActiveXObject("Microsoft.XMLHTTP");
}

self.xmlHttpReq.open("POST", "YourPageHere.asp", true);
self.xmlHttpReq.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8');

self.xmlHttpReq.setRequestHeader("Content-length", QueryString.length);



self.xmlHttpReq.send("?YourQueryString=Value");
1
  • 1
    Uncaught ReferenceError: QueryString is not defined. Commented May 12, 2015 at 3:34
13

Three options here.

  1. Standard JavaScript answer: Use a framework! Most Ajax frameworks will have abstracted you an easy way to make an XMLHTTPRequest POST.

  2. Make the XMLHTTPRequest request yourself, passing post into the open method instead of get. (More information in Using POST method in XMLHTTPRequest (Ajax).)

  3. Via JavaScript, dynamically create a form, add an action, add your inputs, and submit that.

3
  • 5
    XMLHTTPRequest doesn't update the window. Are you trying to say I should end with the AJAX with a document.write(http.responseText)? Commented Sep 25, 2008 at 16:12
  • 13
    Why should one add 30k+ to he's project if he dosent do anything else with the framework ? Commented Nov 7, 2011 at 15:26
  • I made a public Github Repository where, if you add one line of code, you can turn any HTML Form into an Ajax (using Fetch, not XMLHTTPRequest)! github.com/snakysnake/formify.js
    – Clout Hack
    Commented Sep 13, 2021 at 23:32
12

Here is how I wrote it using jQuery. Tested in Firefox and Internet Explorer.

function postToUrl(url, params, newWindow) {
    var form = $('<form>');
    form.attr('action', url);
    form.attr('method', 'POST');
    if(newWindow){ form.attr('target', '_blank'); 
  }

  var addParam = function(paramName, paramValue) {
      var input = $('<input type="hidden">');
      input.attr({ 'id':     paramName,
                 'name':   paramName,
                 'value':  paramValue });
      form.append(input);
    };

    // Params is an Array.
    if(params instanceof Array){
        for(var i=0; i<params.length; i++) {
            addParam(i, params[i]);
        }
    }

    // Params is an Associative array or Object.
    if(params instanceof Object) {
        for(var key in params){
            addParam(key, params[key]);
        }
    }

    // Submit the form, then remove it from the page
    form.appendTo(document.body);
    form.submit();
    form.remove();
}
2
  • 2
    I think the problem here might be that the form is removed before the submission returns. I've heard that in some browsers if you move or remove the form before the submit completes, the handlers won't fire. Instead, remove the form from the document in the handler.
    – Jeff DQ
    Commented May 12, 2011 at 0:18
  • Works like a charm. Tested on Firefox + Chrome + IE11 - Thank you very much for this !
    – Deunz
    Commented Jun 28, 2016 at 11:41
12

The easiest way is using JQuery's AJAX post request:

$.ajax({
    type: "POST",
    url: 'http://www.myrestserver.com/api',
    data: data,
    success: success,
    dataType: dataType
    });

where:

  • data is an object
  • dataType is the data expected by the server (xml, json, script, text, html)
  • url is the address of your RESt server or any function on the server side that accept the HTTP-POST.

Then in the success handler redirect the browser with something like window.location.

3
  • 5
    You didn't mention that the approach you offer is based on the jQuery JavaScript library.
    – DavidRR
    Commented Dec 15, 2013 at 1:32
  • 11
    you've also missed the point of the question - he wants to 'direct a browser to a different page', not make an ajax request.
    – Black
    Commented Apr 3, 2014 at 0:21
  • You could wait for the reply and then document.location={url}; Only place I can imagine this wouldn't work is if you are redirecting to a file download.
    – Epirocks
    Commented Mar 21, 2017 at 10:42
5

The Prototype library includes a Hashtable object, with a ".toQueryString()" method, which allows you to easily turn a JavaScript object/structure into a query-string style string. Since the post requires the "body" of the request to be a query-string formatted string, this allows your Ajax request to work properly as a post. Here's an example using Prototype:

$req = new Ajax.Request("http://foo.com/bar.php",{
    method: 'post',
    parameters: $H({
        name: 'Diodeus',
        question: 'JavaScript posts a request like a form request',
        ...
    }).toQueryString();
};
1
  • 1
    This solution is one of the few that doesn't replace the currently displayed document by the return of the server answer.
    – dothebart
    Commented Dec 30, 2015 at 16:54
5

This works perfectly in my case:

document.getElementById("form1").submit();

You can use it in function like:

function formSubmit() {
     document.getElementById("frmUserList").submit();
} 

Using this you can post all the values of inputs.

5

My solution will encode deeply nested objects, unlike the currently accepted solution by @RakeshPai.

It uses the 'qs' npm library and its stringify function to convert nested objects into parameters.

This code works well with a Rails back-end, although you should be able to modify it to work with whatever backend you need by modifying the options passed to stringify. Rails requires that arrayFormat be set to "brackets".

import qs from "qs"

function normalPost(url, params) {
  var form = document.createElement("form");
  form.setAttribute("method", "POST");
  form.setAttribute("action", url);

  const keyValues = qs
    .stringify(params, { arrayFormat: "brackets", encode: false })
    .split("&")
    .map(field => field.split("="));

  keyValues.forEach(field => {
    var key = field[0];
    var value = field[1];
    var hiddenField = document.createElement("input");
    hiddenField.setAttribute("type", "hidden");
    hiddenField.setAttribute("name", key);
    hiddenField.setAttribute("value", value);
    form.appendChild(hiddenField);
  });
  document.body.appendChild(form);
  form.submit();
}

Example:

normalPost("/people/new", {
      people: [
        {
          name: "Chris",
          address: "My address",
          dogs: ["Jordan", "Elephant Man", "Chicken Face"],
          information: { age: 10, height: "3 meters" }
        },
        {
          name: "Andrew",
          address: "Underworld",
          dogs: ["Doug", "Elf", "Orange"]
        },
        {
          name: "Julian",
          address: "In a hole",
          dogs: ["Please", "Help"]
        }
      ]
    });

Produces these Rails parameters:

{"authenticity_token"=>"...",
 "people"=>
  [{"name"=>"Chris", "address"=>"My address", "dogs"=>["Jordan", "Elephant Man", "Chicken Face"], "information"=>{"age"=>"10", "height"=>"3 meters"}},
   {"name"=>"Andrew", "address"=>"Underworld", "dogs"=>["Doug", "Elf", "Orange"]},
   {"name"=>"Julian", "address"=>"In a hole", "dogs"=>["Please", "Help"]}]}
2
  • This worked great for me with nested objects/array values, thank you
    – sMyles
    Commented Dec 9, 2020 at 23:39
  • @sMyles That is much appreciated and possibly the first time anyone has said thanks on here :-)
    – cmrichards
    Commented Jan 18, 2021 at 2:09
4

Yet another recursive solution, since some of others seem to be broken (I didn't test all of them). This one depends on lodash 3.x and ES6 (jQuery not required):

function createHiddenInput(name, value) {
    let input = document.createElement('input');
    input.setAttribute('type','hidden');
    input.setAttribute('name',name);
    input.setAttribute('value',value);
    return input;
}

function appendInput(form, name, value) {
    if(_.isArray(value)) {
        _.each(value, (v,i) => {
            appendInput(form, `${name}[${i}]`, v);
        });
    } else if(_.isObject(value)) {
        _.forOwn(value, (v,p) => {
            appendInput(form, `${name}[${p}]`, v);
        });
    } else {
        form.appendChild(createHiddenInput(name, value));
    }
}

function postToUrl(url, data) {
    let form = document.createElement('form');
    form.setAttribute('method', 'post');
    form.setAttribute('action', url);

    _.forOwn(data, (value, name) => {
        appendInput(form, name, value);
    });

    form.submit();
}
2

FormData is an option. But FormData is supported by most browsers nowadays.

1

This is like Alan's option 2 (above). How to instantiate the httpobj is left as an excercise.

httpobj.open("POST", url, true);
httpobj.setRequestHeader('Content-Type','application/x-www-form-urlencoded; charset=UTF-8');
httpobj.onreadystatechange=handler;
httpobj.send(post);
1

This is based on beauSD's code using jQuery. It is improved so it works recursively on objects.

function post(url, params, urlEncoded, newWindow) {
    var form = $('<form />').hide();
    form.attr('action', url)
        .attr('method', 'POST')
        .attr('enctype', urlEncoded ? 'application/x-www-form-urlencoded' : 'multipart/form-data');
    if(newWindow) form.attr('target', '_blank');

    function addParam(name, value, parent) {
        var fullname = (parent.length > 0 ? (parent + '[' + name + ']') : name);
        if(value instanceof Object) {
            for(var i in value) {
                addParam(i, value[i], fullname);
            }
        }
        else $('<input type="hidden" />').attr({name: fullname, value: value}).appendTo(form);
    };

    addParam('', params, '');

    $('body').append(form);
    form.submit();
}
1

You could dynamically add the form using DHTML and then submit.

1

The accepted answer will reload the page like a native form submit. This modified version, will submit through XHR:

function post(path, params) {
  const form = document.createElement('form');

  for (const key in params) {
    if (params.hasOwnProperty(key)) {
      const hiddenField = document.createElement('input');
      hiddenField.type = 'hidden';
      hiddenField.name = key;
      hiddenField.value = params[key];

      form.appendChild(hiddenField);
    }
  }
  var button = form.ownerDocument.createElement('input');
  button.type = 'submit';
  form.appendChild(button);

  form.onsubmit = async function (e) {
    console.log('hi');

    e.preventDefault();
    const form = e.currentTarget;

    try {
      const formData = new FormData(form);
      const response = await fetch(path, {
        method: 'POST',
        body: formData,
      });

      console.log(response);
    } catch (error) {
      console.error(error);
    }
  };

  document.body.appendChild(form);
  button.click();
}
1

I use the document.forms and loop it to get all the elements in the form, then send via XMLHttpRequest. So this is my solution for javascript / ajax submission (with all HTML included as an example):

function smc() {
  var http = new XMLHttpRequest();
  var url = "yourphpfile.php";
  var x = document.forms[0];
  var xstr = "";
  var i;
  for (i = 0; i < x.length; i++) {
    if (i == 0) {
      xstr += x.elements[i].name + "=" + x.elements[i].value;
    } else {
      xstr += "&" + x.elements[i].name + "=" + x.elements[i].value;
    }
  }

  http.open("POST", url, true);
  http.setRequestHeader("Content-type", "application/x-www-form-urlencoded");

  http.onreadystatechange = function() {
    if (http.readyState == 4 && http.status == 200) {
      // do whatever you want to with the html output response here
    }
  }

  http.send(xstr);

}
<!DOCTYPE html>
<html>

<body>
  <form>
    First name: <input type="text" name="fname" value="Donald"><br> Last name: <input type="text" name="lname" value="Duck"><br> Addr1: <input type="text" name="add" value="123 Pond Dr"><br> City: <input type="text" name="city" value="Duckopolis"><br>
  </form>

  <button onclick="smc()">Submit</button>
</body>

</html>

0

The method I use to post and direct a user automatically to another page is to just write a hidden form and then auto submit it. Be assured that the hidden form takes absolutely no space on the web page. The code would be something like this:

    <form name="form1" method="post" action="somepage.php">
    <input name="fielda" type="text" id="fielda" type="hidden">

    <textarea name="fieldb" id="fieldb" cols="" rows="" style="display:none"></textarea>
</form>
    document.getElementById('fielda').value="some text for field a";
    document.getElementById('fieldb').innerHTML="some text for multiline fieldb";
    form1.submit();

Application of auto submit

An application of an auto submit would be directing form values that the user automatically put in on the other page back to that page. Such an application would be like this:

fieldapost=<?php echo $_post['fielda'];>
if (fieldapost !="") {
document.write("<form name='form1' method='post' action='previouspage.php'>
  <input name='fielda' type='text' id='fielda' type='hidden'>
</form>");
document.getElementById('fielda').value=fieldapost;
form1.submit();
}
0

Here is how I do it.

function redirectWithPost(url, data){
        var form = document.createElement('form');
        form.method = 'POST';
        form.action = url;

        for(var key in data){
            var input = document.createElement('input');
            input.name = key;
            input.value = data[key];
            input.type = 'hidden';
            form.appendChild(input)
        }
        document.body.appendChild(form);
        form.submit();
    }
0

jQuery plugin for redirect with POST or GET:

https://github.com/mgalante/jquery.redirect/blob/master/jquery.redirect.js

To test, include the above .js file or copy/paste the class into your code, then use the code here, replacing "args" with your variable names, and "values" with the values of those respective variables:

$.redirect('demo.php', {'arg1': 'value1', 'arg2': 'value2'});
1
0

None of the above solutions handled deep nested params with just jQuery, so here is my two cents solution.

If you're using jQuery and you need to handle deep nested parameters, you can use this function below:

    /**
     * Original code found here: https://github.com/mgalante/jquery.redirect/blob/master/jquery.redirect.js
     * I just simplified it for my own taste.
     */
    function postForm(parameters, url) {

        // generally we post the form with a blank action attribute
        if ('undefined' === typeof url) {
            url = '';
        }


        //----------------------------------------
        // SOME HELPER FUNCTIONS
        //----------------------------------------
        var getForm = function (url, values) {

            values = removeNulls(values);

            var form = $('<form>')
                .attr("method", 'POST')
                .attr("action", url);

            iterateValues(values, [], form, null);
            return form;
        };

        var removeNulls = function (values) {
            var propNames = Object.getOwnPropertyNames(values);
            for (var i = 0; i < propNames.length; i++) {
                var propName = propNames[i];
                if (values[propName] === null || values[propName] === undefined) {
                    delete values[propName];
                } else if (typeof values[propName] === 'object') {
                    values[propName] = removeNulls(values[propName]);
                } else if (values[propName].length < 1) {
                    delete values[propName];
                }
            }
            return values;
        };

        var iterateValues = function (values, parent, form, isArray) {
            var i, iterateParent = [];
            Object.keys(values).forEach(function (i) {
                if (typeof values[i] === "object") {
                    iterateParent = parent.slice();
                    iterateParent.push(i);
                    iterateValues(values[i], iterateParent, form, Array.isArray(values[i]));
                } else {
                    form.append(getInput(i, values[i], parent, isArray));
                }
            });
        };

        var getInput = function (name, value, parent, array) {
            var parentString;
            if (parent.length > 0) {
                parentString = parent[0];
                var i;
                for (i = 1; i < parent.length; i += 1) {
                    parentString += "[" + parent[i] + "]";
                }

                if (array) {
                    name = parentString + "[" + name + "]";
                } else {
                    name = parentString + "[" + name + "]";
                }
            }

            return $("<input>").attr("type", "hidden")
                .attr("name", name)
                .attr("value", value);
        };


        //----------------------------------------
        // NOW THE SYNOPSIS
        //----------------------------------------
        var generatedForm = getForm(url, parameters);

        $('body').append(generatedForm);
        generatedForm.submit();
        generatedForm.remove();
    }

Here is an example of how to use it. The html code:

<button id="testButton">Button</button>

<script>
    $(document).ready(function () {
        $("#testButton").click(function () {
            postForm({
                csrf_token: "abcd",
                rows: [
                    {
                        user_id: 1,
                        permission_group_id: 1
                    },
                    {
                        user_id: 1,
                        permission_group_id: 2
                    }
                ],
                object: {
                    apple: {
                        color: "red",
                        age: "23 days",
                        types: [
                            "golden",
                            "opal",
                        ]
                    }
                },
                the_null: null, // this will be dropped, like non-checked checkboxes are dropped
            });
        });
    });
</script>

And if you click the test button, it will post the form and you will get the following values in POST:

array(3) {
  ["csrf_token"] => string(4) "abcd"
  ["rows"] => array(2) {
    [0] => array(2) {
      ["user_id"] => string(1) "1"
      ["permission_group_id"] => string(1) "1"
    }
    [1] => array(2) {
      ["user_id"] => string(1) "1"
      ["permission_group_id"] => string(1) "2"
    }
  }
  ["object"] => array(1) {
    ["apple"] => array(3) {
      ["color"] => string(3) "red"
      ["age"] => string(7) "23 days"
      ["types"] => array(2) {
        [0] => string(6) "golden"
        [1] => string(4) "opal"
      }
    }
  }
}

Note: if you want to post the form to another url than the current page, you can specify the url as the second argument of the postForm function.

So for instance (to re-use your example):

postForm({'q':'a'}, 'http://example.com/');

Hope this helps.

Note2: the code was taken from the redirect plugin. I basically just simplified it for my needs.

0

You could use jQuery's trigger method to submit the form, just like you press a button, like so,

$('form').trigger('submit')

it will submit on the browser.

1
  • You dont even need jQuery for that. document.querySelector("form").submit() would be the same with any extra framework Commented Feb 5, 2021 at 13:24
0

Try

function post_to_url(url, obj) {
  let id=`form_${+new Date()}`;
  document.body.innerHTML+=`
    <form id="${id}" action="${url}" method="POST">
      ${Object.keys(obj).map(k=>`
        <input type="hidden" name="${k}" value="${obj[k]}">
      `)}
    </form>`
  this[id].submit();  
}

// TEST - in second param object can have more keys
function jump() { post_to_url('https://example.com/', {'q':'a'}); }
Open chrome>networks and push button:
<button onclick="jump()">Send POST</button>

Not the answer you're looking for? Browse other questions tagged or ask your own question.