1637

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?

Edit

I'm sorry I was not clear. 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.

Kamil Kiełczewski
  • 53,729
  • 20
  • 259
  • 241
Joseph Holsten
  • 19,514
  • 6
  • 23
  • 28
  • 1
    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'}); https://github.com/mgalante/jquery.redirect/blob/master/jquery.redirect.js – OG Sean Jul 09 '18 at 00:16
  • The `document` object doesn't have a `location.href` you need a to use `window`. – Justin Liu Jun 12 '20 at 15:07

31 Answers31

2250

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.

NullDev
  • 4,714
  • 4
  • 23
  • 43
Rakesh Pai
  • 24,847
  • 3
  • 23
  • 29
  • 11
    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 Oct 14 '15 at 06:36
  • 23
    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 Oct 20 '15 at 16:41
  • 1
    I created a gist with the code https://gist.github.com/lingceng/175f493450636e505cc3 – lingceng Nov 21 '15 at 09:19
  • 4
    amazing this is not natively supported either by html nor javascript not jquery .. you have to code this. – eugene Feb 17 '16 at 08:02
  • 1
    Is it worth removing the form after it has been added to the DOM? I can foresee issues with `document.forms` – mricci May 06 '16 at 00:33
  • 2
    why is method in parameters since its called post and should be used only for post? – Srneczek May 31 '16 at 17:19
  • Is there no way to simulate this effect with ajax? What is the magic in the HTML form that accomplishes this, that it can't be done without it? – temporary_user_name Jun 24 '16 at 18:02
  • 2
    If you wanted this post to happen in a new tab : `var tabWindowId = window.open('about:blank', '_blank'); var form = tabWindowId.document.createElement("form"); tabWindowId.document.body.appendChild(form);` – Deunz Jun 28 '16 at 07:59
  • 16
    @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 – Ken Bellows Jul 07 '16 at 13:07
  • 2
    @Aerovistae The difference is that AJAX doesn't navigate to a new page, it just returns the data to the script that made the request. Hypothetically you could probably fake it by making an AJAX POST request with the content type set to "text/html" to get the content of the new page, then replace the current page with the HTML you get back, but the URL won't change, and doesn't the whole idea make you gag a little bit anyway? (That being said, similar methods are used for *sections* of pages in Single Page Application frameworks like Angular and Ember) – Ken Bellows Jul 07 '16 at 13:11
  • @RakeshPai Why do you have the 'method' input arg when this is only for 'POST'? – Ethan Jul 08 '17 at 02:22
  • 1
    @Ethan It's an optional argument, and defaults to POST. Changing methods doesn't cost anything, so I just put it in there. Feel free to remove it if it bothers you. – Rakesh Pai Jul 10 '17 at 09:01
  • @stevemao depends if you need to support IE6-9 or not – Andy Oct 31 '17 at 22:50
  • 7
    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()}); – Davidson Lima Nov 22 '17 at 16:09
  • Shouldn't it be upper case "POST" (in the line method = method || "post")? I have never tried lower case, but I guess most IIS's don't care. I know of one IIS where lower case won't work. – www-0av-Com Jan 02 '18 at 12:42
  • Hi, it works pretty well. But it always creates new element `var form = document.createElement("form");` There is any possibilities to add it to already existing POST method? – Damian Silkowski Jan 26 '18 at 12:48
  • 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. – Stefan Steiger Mar 13 '18 at 16:27
  • @www-0av-Com. The `post` here is not the HTTP verb, but the form method, which is case-insensitive. `
    ` is perfectly acceptable.
    – TRiG Nov 21 '19 at 16:06
  • @Rakesh and all, can someoneh help here please: https://stackoverflow.com/questions/61313006/how-to-add-an-extra-submit-button-to-gravity-form/61316408?noredirect=1#comment108476711_61316408 – shireef khatab Apr 20 '20 at 10:38
  • Clever solution. Instead of using JS to create the form, I manually created a form and added the hidden attribute to it with readonly in the text fields. Then I used JS to fill in the form and submit it. – Haddock-san Apr 22 '20 at 15:21
  • So you are telling me there is no way in JavaScript to make a normal POST request without this HTML hack? – Lorenzo Von Matterhorn Oct 23 '20 at 07:22
137

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();
}
Kerem Baydoğan
  • 9,716
  • 1
  • 37
  • 49
Ryan Delucchi
  • 7,468
  • 13
  • 46
  • 59
  • 7
    Slightly modified this to support arrays and objects https://gist.github.com/hom3chuk/692bf12fe7dac2486212 – НЛО Sep 28 '15 at 22:39
  • 3
    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. – Stefan Steiger Mar 13 '18 at 16:26
  • If your needs are simple, then this function is unnecessary. This one-liner is sufficient: `$("
    ").appendTo("body").submit();`
    – rinogo Jul 17 '19 at 19:31
76

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...

Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123
Alexandre Victoor
  • 2,857
  • 2
  • 25
  • 27
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);
}
Community
  • 1
  • 1
Jonny Buchanan
  • 58,371
  • 16
  • 137
  • 146
  • 6
    Do you need to remove the child after submission? Doesn't the page go away anyway? – Nils May 31 '12 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. – Miloš Jul 20 '12 at 07:07
  • 6
    @CantucciHQ The page might just as well stay unchanged even if form target is not set. There is [204 No Content](http://stackoverflow.com/q/3283071/1353187), for example. – Eugene Ryabtsev Jan 30 '14 at 11:41
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!
Vasil Lukach
  • 3,383
  • 3
  • 27
  • 36
Kendall Hopkins
  • 39,091
  • 16
  • 60
  • 85
32

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.

Kerwin Sneijders
  • 549
  • 8
  • 28
gaby de wilde
  • 1,145
  • 11
  • 6
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();
Jon Cage
  • 33,172
  • 32
  • 120
  • 206
Head
  • 4,391
  • 3
  • 28
  • 18
27

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(); 
}
kritzikratzi
  • 16,501
  • 1
  • 25
  • 38
  • 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. – kritzikratzi May 26 '12 at 16:09
  • 3
    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 Nov 18 '13 at 01:07
  • 2
    @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. – kritzikratzi Nov 18 '13 at 04:20
18

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});
Joseph Holsten
  • 19,514
  • 6
  • 23
  • 28
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();
};
Willi Mentzel
  • 21,499
  • 16
  • 88
  • 101
emragins
  • 3,368
  • 2
  • 29
  • 47
14

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.

Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123
Alan Storm
  • 157,413
  • 86
  • 367
  • 554
14

The easiest way is using 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.

Jasmine Hegman
  • 553
  • 6
  • 19
JLavoie
  • 13,438
  • 7
  • 29
  • 35
  • 5
    You didn't mention that the approach you offer is based on the **jQuery** JavaScript library. – DavidRR Dec 15 '13 at 01:32
  • 8
    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 Apr 03 '14 at 00: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 Mar 21 '17 at 10:42
13

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");
BBog
  • 3,425
  • 5
  • 30
  • 63
Katy
  • 1,054
  • 7
  • 15
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();
}
Johnny Five
  • 788
  • 1
  • 9
  • 27
beauburrier
  • 1,311
  • 1
  • 16
  • 18
  • 1
    Worked for me. Thanks. (Tested in Chrome) – dannie.f Dec 23 '10 at 13:43
  • 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 May 12 '11 at 00:18
  • Works like a charm. Tested on Firefox + Chrome + IE11 - Thank you very much for this ! – Deunz Jun 28 '16 at 11:41
7

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();
};
Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123
Adam Ness
  • 5,990
  • 4
  • 25
  • 39
  • 1
    This solution is one of the few that doesn't replace the currently displayed document by the return of the server answer. – dothebart Dec 30 '15 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.

Johnny Five
  • 788
  • 1
  • 9
  • 27
Chintan Thummar
  • 1,214
  • 14
  • 28
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"]}]}
cmrichards
  • 1,679
  • 16
  • 25
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();
}
mpen
  • 237,624
  • 230
  • 766
  • 1,119
2

FormObject is an option. But FormObject is not supported by most browsers now.

lingceng
  • 2,289
  • 1
  • 16
  • 19
1

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

Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123
AnthonyWJones
  • 178,910
  • 32
  • 227
  • 302
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

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

          <!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>

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

           xstr = ta+tb;
      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);

              }
         </script>

         </body>
     </html>
drtechno
  • 268
  • 2
  • 9
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();
}
bobef
  • 942
  • 9
  • 13
0

You could use a library like jQuery and its $.post method.

Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123
Bill Turner
  • 3,631
  • 1
  • 18
  • 25
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();
}
rauprog
  • 183
  • 1
  • 8
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();
    }
nikksan
  • 2,699
  • 2
  • 16
  • 25
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'});
OG Sean
  • 760
  • 6
  • 17
  • This was also mentioned here: https://stackoverflow.com/questions/8389646/send-post-data-on-redirect-with-javascript-jquery – OG Sean Jul 09 '18 at 00:22
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.

Canaan Etai
  • 2,144
  • 2
  • 18
  • 15
  • You dont even need jQuery for that. `document.querySelector("form").submit()` would be the same with any extra framework – Ulrich Stark Feb 05 '21 at 13:24
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.

ling
  • 7,505
  • 3
  • 41
  • 39
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>
Kamil Kiełczewski
  • 53,729
  • 20
  • 259
  • 241
-3

You could make an AJAX call (likely using a library such as using Prototype.js or JQuery). AJAX can handle both GET and POST options.

Diodeus - James MacFarlane
  • 107,156
  • 31
  • 147
  • 171