Запрос на отправку JavaScript как отправка формы

Я пытаюсь открыть в браузере другую страницу. Если бы я хотел получить запрос GET, я бы сказал

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

Но ресурс, к которому я пытаюсь получить доступ, не будет отвечать должным образом, если я не использую запрос POST. Если бы это не было динамически сгенерировано, я мог бы использовать HTML

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

Затем я просто отправлял форму из DOM.

Но на самом деле мне нужен код JavaScript, который позволяет мне сказать

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

Какая лучшая кроссбраузерная реализация?

Изменить

Мне жаль, что я не понял. Мне нужно решение, которое изменяет местоположение браузера, как при отправке формы. Если это возможно с помощью XMLHttpRequest, это не очевидно. И это не должно быть асинхронным или использовать XML, поэтому Ajax - не ответ.


person Joseph Holsten    schedule 25.09.2008    source источник
comment
Как упоминалось в другом потоке, существует плагин jquery .redirect, который работает с методом POST или GET. Он создает форму со скрытыми входами и отправляет ее за вас. Пример: $ .redirect ('demo.php', {'arg1': 'value1', 'arg2': 'value2'}); github.com/mgalante/jquery.redirect/blob/master/   -  person OG Sean    schedule 09.07.2018
comment
У объекта document нет location.href, необходимого для использования window.   -  person Justin Liu    schedule 12.06.2020


Ответы (31)


Динамически создавать <input> в форме и отправлять его

/**
 * 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();
}

Пример:

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

РЕДАКТИРОВАТЬ: так как за это так много проголосовали, я предполагаю, что люди будут часто копировать это. Поэтому я добавил проверку hasOwnProperty, чтобы исправить любые непреднамеренные ошибки.

person Rakesh Pai    schedule 25.09.2008
comment
А как насчет массивов в параметрах данных? JQuery post () интерпретирует, например: data: {array: [1, 2, 3]} как? Array = 1 & array = 2 & array = 3. Этот код дает другой результат. - person Scit; 14.10.2015
comment
Предупреждение: несмотря на множество положительных отзывов, это решение ограничено и не обрабатывает массивы или вложенные объекты внутри формы. В противном случае это отличный ответ. - person emragins; 20.10.2015
comment
Я создал суть с кодом gist.github.com/lingceng/175f493450636e505cc3 - person lingceng; 21.11.2015
comment
удивительно, что это изначально не поддерживается ни html, ни javascript, а не jquery .. вы должны это закодировать. - person eugene; 17.02.2016
comment
Стоит ли удалять форму после того, как она была добавлена ​​в DOM? Я могу предвидеть проблемы с document.forms - person mricci; 06.05.2016
comment
почему метод находится в параметрах, так как он называется постом и должен использоваться только для поста? - person Srneczek; 31.05.2016
comment
Нет возможности смоделировать этот эффект с помощью ajax? Какая магия в HTML-форме позволяет добиться этого, что без нее этого не обойтись? - person temporary_user_name; 24.06.2016
comment
Если вы хотите, чтобы этот пост появился в новой вкладке: var tabWindowId = window.open('about:blank', '_blank'); var form = tabWindowId.document.createElement("form"); tabWindowId.document.body.appendChild(form); - person Deunz; 28.06.2016
comment
@mricci Цель этого фрагмента - перенаправить браузер на новый URL-адрес, указанный действием; если вы остаетесь на той же странице, вы можете просто использовать традиционный AJAX для POST ваших данных. Поскольку браузер должен переходить на новую страницу, содержимое DOM текущей страницы не имеет значения. - person Ken Bellows; 07.07.2016
comment
@Aerovistae Разница в том, что AJAX не переходит на новую страницу, а просто возвращает данные скрипту, который сделал запрос. Гипотетически вы, вероятно, могли бы подделать это, сделав запрос AJAX POST с типом содержимого, установленным на text / html, чтобы получить содержимое новой страницы, а затем заменить текущую страницу на HTML, который вы получите обратно, но URL-адрес не изменится, и разве сама идея не заставляет вас немного заткнуть рот? (При этом аналогичные методы используются для разделов страниц в фреймворках одностраничных приложений, таких как Angular и Ember) - person Ken Bellows; 07.07.2016
comment
@RakeshPai Почему у вас есть входной аргумент 'method', когда он предназначен только для 'POST'? - person Ethan; 08.07.2017
comment
@Ethan Это необязательный аргумент, по умолчанию используется POST. Смена методов ничего не стоит, поэтому я просто вставил это туда. Не стесняйтесь снимать его, если он вас беспокоит. - person Rakesh Pai; 10.07.2017
comment
@stevemao зависит от того, нужно ли вам поддерживать IE6-9 или нет - person Andy; 01.11.2017
comment
Пользователи Python, Django и, возможно, Flask увидят эту ошибку: Запрещено (403). Ошибка проверки CSRF. Запрос прерван., Если форма создается с нуля. В этом случае вы должны передать токен csrf следующим образом: post ('/ contact /', {name: 'Johnny Bravo', csrfmiddlewaretoken: $ (# csrf_token) .val ()}); - person Davidson Lima; 22.11.2017
comment
Разве это не должно быть POST в верхнем регистре (в строке method = method || post)? Я никогда не пробовал строчные буквы, но, думаю, большинству IIS наплевать. Я знаю один IIS, в котором строчные буквы не работают. - person www-0av-Com; 02.01.2018
comment
Привет, работает очень хорошо. Но он всегда создает новый элемент var form = document.createElement("form"); Есть ли возможность добавить его к уже существующему методу POST? - person Damian Silkowski; 26.01.2018
comment
Если значение содержит xml-символ опасности, это не будет работать в ASP.NET encodeUriComponent (значение) требуется. Затем UrlDecode также требуется на стороне сервера. - person Stefan Steiger; 13.03.2018
comment
@ www-0av-Com. post здесь не HTTP-команда, а метод формы, который нечувствителен к регистру. <form method="post"> вполне приемлемо. - person TRiG; 21.11.2019
comment
@Rakesh и все такое, может кто-нибудь здесь поможет: stackoverflow.com/questions/61313006/ - person shireef khatab; 20.04.2020
comment
Умное решение. Вместо того, чтобы использовать JS для создания формы, я вручную создал форму и добавил к ней скрытый атрибут с только для чтения в текстовых полях. Затем я использовал JS, чтобы заполнить форму и отправить ее. - person Haddock-san; 22.04.2020
comment
Итак, вы говорите мне, что в JavaScript нет способа сделать обычный запрос POST без этого HTML-хака? - person Lorenzo Von Matterhorn; 23.10.2020

Это будет версия выбранного ответа с использованием 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();
}
person Ryan Delucchi    schedule 04.04.2011
comment
Немного изменены для поддержки массивов и объектов gist.github.com/hom3chuk/692bf12fe7dac2486212 - person НЛО; 29.09.2015
comment
Если значение содержит символ xml dangeours, это не будет работать в ASP.NET encodeUriComponent (значение) требуется. Затем UrlDecode также требуется на стороне сервера. - person Stefan Steiger; 13.03.2018
comment
Если ваши потребности просты, то в этой функции нет необходимости. Этого однострочного текста достаточно: $("<form method='POST' action='https://example.com'><input type='hidden' name='q' value='a'/></form>").appendTo("body").submit(); - person rinogo; 17.07.2019

Простая быстрая и грязная реализация ответа @Aaron:

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

Конечно, вам лучше использовать структуру JavaScript, такую ​​как Prototype или jQuery ...

person Alexandre Victoor    schedule 25.09.2008
comment
Есть ли способ сделать это без загрузки веб-страницы в текущем окне / вкладке браузера? - person pbreitenbach; 25.09.2010
comment
Как мне вставить сюда csrf? - person Shulz; 20.09.2020
comment
@Shulz Вы можете добавить еще один скрытый ввод с [name], установленным для ключа, и [value], установленным для значения токена. - person Amir Savand; 14.12.2020

Использование функции createElement, представленной в этот ответ, который необходим из-за нарушение IE с атрибутом name на элементах, обычно созданных с 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);
}
person Jonny Buchanan    schedule 25.09.2008
comment
Вам нужно удалить ребенка после подачи? Страница все равно не уходит? - person Nils; 01.06.2012
comment
Нет смысла удалять ребенка после отправки, за исключением случаев, когда используется сеанс и эти данные сохраняются. - person Miloš; 20.07.2012
comment
@CantucciHQ Страница может оставаться неизменной, даже если цель формы не установлена. Например, есть 204 No Content. - person Eugene Ryabtsev; 30.01.2014

Ответ Ракеша Пая потрясающий, но есть проблема, которая возникает у меня (в Safari), когда я пытаюсь опубликовать форму с поле с именем submit. Например, post_to_url("http://google.com/",{ submit: "submit" } );. Я немного исправил функцию, чтобы обойти это столкновение с переменным пространством.

    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!
person Kendall Hopkins    schedule 15.07.2010
comment
2018 и все еще не лучший ответ? - person iiirxs; 20.06.2018
comment
Есть ли в Safari проблема, требующая решения? - person Flimm; 13.10.2020
comment
решение не работает в браузере Safari и браузере Chrome iPhone 11 / браузере Safari .. во время навигации мы теряем сетевое соединение. может кто-нибудь посоветовать по этому поводу, пожалуйста. @Flimm, - person Kishore Konangi; 26.05.2021

Нет. У вас не может быть запроса на публикацию JavaScript, как отправки формы.

Вы можете создать форму в HTML, а затем отправить ее с помощью JavaScript. (как много раз объяснялось на этой странице).

Вы можете создать HTML самостоятельно, вам не нужен JavaScript для написания HTML. Было бы глупо, если бы люди это предложили.

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

Ваша функция просто настроит форму так, как вы этого хотите.

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

Затем используйте это как.

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

Но я бы просто оставил функцию и просто сделал.

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

Наконец, решение о стиле находится в файле ccs.

#ninja{ 
  display:none;
}

Лично я считаю, что к формам следует обращаться по имени, но сейчас это не важно.

person gaby de wilde    schedule 19.08.2013

это ответ rakesh, но с поддержкой массивов (что довольно часто встречается в формах):

простой 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();
}

о, и вот версия jquery: (немного другой код, но сводится к одному и тому же)

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(); 
}
person kritzikratzi    schedule 22.03.2012
comment
p.s. Теперь мне нравится использовать эту функцию, но вместо того, чтобы отправлять форму в конце, я просто возвращаю ее обратно вызывающему. таким образом я могу легко установить дополнительные атрибуты или сделать с ним что-то еще, если это необходимо. - person kritzikratzi; 26.05.2012
comment
Большой! очень полезный. Небольшое изменение для людей, которые полагаются на PHP на стороне сервера этой формы, я изменил addField (key, params [key] [i]) на addField (key + '[]', params [key] [i]). Это делает $ _POST [ключ] доступным в виде массива. - person Thava; 18.11.2013
comment
@Thava вы также можете установить name = bla [] в поле ввода. в любом случае, есть языки, отличные от php, которые не поддерживают синтаксис [], поэтому я оставляю это без изменений. - person kritzikratzi; 18.11.2013

Если у вас установлен Prototype, вы можете усилить код, чтобы сгенерировать и отправить скрытую форму следующим образом:

 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();
person Head    schedule 23.01.2009

Одно из решений - создать форму и отправить ее. Одна реализация

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();
}

Таким образом, я могу реализовать букмарклет для сокращения URL-адресов с помощью простого

javascript:post_to_url('http://is.gd/create.php', {'URL': location.href});
person Joseph Holsten    schedule 25.09.2008

Что ж, жаль, что я не прочитал все другие сообщения, чтобы не терять время на создание этого из ответа Ракеша Пая. Вот рекурсивное решение, которое работает с массивами и объектами. Нет зависимости от jQuery.

Добавлен сегмент для обработки случаев, когда вся форма должна быть отправлена ​​как массив. (т.е. там, где нет объекта-оболочки вокруг списка элементов)

/**
 * 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();
};
person emragins    schedule 27.01.2014
comment
Похоже, это тоже неправильно кодирует вложенные объекты. - person mpen; 11.05.2016
comment
@mpen у тебя есть скрипка? - person emragins; 11.05.2016
comment
Нет простите. Писать самому было достаточно легко; не стоит тратить время на отладку. - person mpen; 12.05.2016

Я бы пошел по маршруту Ajax, как предлагали другие, с чем-то вроде:

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");
person Katy    schedule 25.09.2008
comment
Uncaught ReferenceError: QueryString не определен. - person Chase Roberts; 12.05.2015

Здесь три варианта.

  1. Стандартный ответ JavaScript: используйте фреймворк! Большинство фреймворков Ajax предоставят вам простой способ сделать XMLHTTPRequest POST.

  2. Сделайте запрос XMLHTTPRequest самостоятельно, передав сообщение в метод open вместо get. (Подробнее см. Использование метода POST в XMLHTTPRequest (Ajax) .)

  3. С помощью JavaScript динамически создайте форму, добавьте действие, добавьте свои данные и отправьте их.

person Alan Storm    schedule 25.09.2008
comment
XMLHTTPRequest не обновляет окно. Вы хотите сказать, что я должен закончить AJAX с помощью document.write (http.responseText)? - person Joseph Holsten; 25.09.2008
comment
Зачем нужно добавлять 30k + к своему проекту, если он не хочет делать что-то еще с фреймворком? - person Rafael Herscovici; 07.11.2011

Самый простой способ - использовать Ajax Post Request:

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

куда:

  • данные - это объект
  • dataType - это данные, ожидаемые сервером (xml, json, script, text, html)
  • url - это адрес вашего сервера RESt или любой функции на стороне сервера, которая принимает HTTP-POST.

Затем в обработчике успеха перенаправьте браузер с помощью чего-то вроде window.location.

person JLavoie    schedule 10.09.2013
comment
Вы не упомянули, что предлагаемый вами подход основан на библиотеке JavaScript jQuery. - person DavidRR; 15.12.2013
comment
вы также упустили суть вопроса - он хочет «направить браузер на другую страницу», а не делать запрос ajax. - person Black; 03.04.2014
comment
Вы можете дождаться ответа, а затем document.location = {url}; Единственное место, где я могу представить, что это не сработает, - это если вы перенаправляетесь на загрузку файла. - person Epirocks; 21.03.2017

Вот как я написал это с помощью jQuery. Протестировано в Firefox и 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();
}
person beauburrier    schedule 21.09.2010
comment
Работал у меня. Спасибо. (Проверено в Chrome) - person dannie.f; 23.12.2010
comment
Я думаю, проблема здесь может заключаться в том, что форма удаляется до того, как отправка возвращается. Я слышал, что в некоторых браузерах, если вы переместите или удалите форму до завершения отправки, обработчики не сработают. Вместо этого удалите форму из документа в обработчике. - person Jeff DQ; 12.05.2011
comment
Работает как шарм. Протестировано в Firefox + Chrome + IE11 - Большое спасибо за это! - person Deunz; 28.06.2016

Библиотека Prototype включает объект Hashtable с методом ".toQueryString ()", который позволяет вам чтобы легко превратить объект / структуру JavaScript в строку стиля строки запроса. Поскольку сообщение требует, чтобы «тело» запроса было строкой в ​​формате строки запроса, это позволяет вашему запросу Ajax правильно работать как сообщение. Вот пример использования 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();
};
person Adam Ness    schedule 25.09.2008
comment
Это решение - одно из немногих, в котором текущий отображаемый документ не заменяется ответом сервера. - person dothebart; 30.12.2015

В моем случае это отлично работает:

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

Вы можете использовать его в таких функциях, как:

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

Используя это, вы можете опубликовать все значения входов.

person Chintan Thummar    schedule 29.03.2013

Мое решение будет кодировать глубоко вложенные объекты, в отличие от принятого в настоящее время решения от @RakeshPai.

Он использует библиотеку npm qs и ее функцию stringify для преобразования вложенных объектов в параметры.

Этот код хорошо работает с серверной частью Rails, хотя вы должны иметь возможность модифицировать его для работы с любым нужным вам сервером, изменив параметры, переданные в stringify. Rails требует, чтобы arrayFormat был установлен в "скобки".

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();
}

Пример:

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"]
        }
      ]
    });

Производит следующие параметры Rails:

{"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"]}]}
person cmrichards    schedule 31.08.2018
comment
Это отлично сработало для меня с вложенными объектами / значениями массивов, спасибо - person sMyles; 10.12.2020
comment
@sMyles Это очень ценится и, возможно, впервые здесь кто-то сказал спасибо :-) - person cmrichards; 18.01.2021

Еще одно рекурсивное решение, поскольку некоторые из них кажутся неисправными (я не тестировал их все). Это зависит от lodash 3.x и ES6 ( jQuery не требуется):

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();
}
person mpen    schedule 11.05.2016

FormObject - это вариант. Но FormObject сейчас не поддерживается большинством браузеров.

person lingceng    schedule 21.11.2015

Это похоже на вариант 2 Алана (см. Выше). Как создать экземпляр httpobj оставлено как упражнение.

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

Это основано на коде beauSD с использованием jQuery. Он улучшен, поэтому он рекурсивно работает с объектами.

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();
}
person bobef    schedule 27.05.2011

Вы можете динамически добавить форму с помощью DHTML, а затем отправить.

person AnthonyWJones    schedule 25.09.2008

Вы можете использовать такую ​​библиотеку, как jQuery, и ее метод $ .post.

person Bill Turner    schedule 25.09.2008
comment
Обратите внимание, что $ .post - это только AJAX. - person Bryan Larsen; 27.03.2012

Я использую java document.forms и зацикливаю его, чтобы получить все элементы в форме, а затем отправляю через xhttp. Итак, это мое решение для отправки javascript / ajax (со всем включенным html в качестве примера):

          <!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>
person drtechno    schedule 20.01.2018

Метод, который я использую для публикации и автоматического направления пользователя на другую страницу, - это просто написать скрытую форму и затем автоматически отправить ее. Будьте уверены, что скрытая форма абсолютно не занимает места на веб-странице. Код будет примерно таким:

    <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();

Применение автоматической отправки

Приложение автоматической отправки будет направлять значения формы, которые пользователь автоматически помещает на другую страницу, обратно на эту страницу. Такое приложение было бы таким:

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();
}
person rauprog    schedule 25.09.2017

Вот как я это делаю.

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();
    }
person nikksan    schedule 06.03.2018

Плагин jQuery для перенаправления с помощью POST или GET:

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

Для тестирования включите указанный выше файл .js или скопируйте / вставьте класс в свой код, затем используйте приведенный здесь код, заменив «args» именами переменных, а «values» - значениями этих соответствующих переменных:

$.redirect('demo.php', {'arg1': 'value1', 'arg2': 'value2'});
person OG Sean    schedule 09.07.2018
comment
Это также упоминалось здесь: stackoverflow.com/questions/8389646/ - person OG Sean; 09.07.2018

Ни одно из вышеперечисленных решений не обрабатывало глубокие вложенные параметры только с помощью jQuery, поэтому вот мое решение за два цента.

Если вы используете jQuery и вам нужно обрабатывать глубоко вложенные параметры, вы можете использовать эту функцию ниже:

    /**
     * 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();
    }

Вот пример того, как его использовать. HTML-код:

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

И если вы нажмете кнопку тестирования, он опубликует форму, и вы получите следующие значения в 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"
      }
    }
  }
}

Примечание: если вы хотите опубликовать форму по URL-адресу, отличному от URL-адреса текущей страницы, вы можете указать URL-адрес в качестве второго аргумента функции postForm.

Так, например (чтобы повторно использовать ваш пример):

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

Надеюсь это поможет.

Примечание 2: код был взят из плагина перенаправления . Я просто упростил его для своих нужд.

person ling    schedule 10.12.2019

Вы можете использовать метод триггера jQuery для отправки формы, точно так же, как вы нажимаете кнопку, например,

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

он будет отправлен в браузере.

person Canaan Etai    schedule 13.02.2019
comment
Для этого вам даже не нужен jQuery. document.querySelector("form").submit() будет таким же с любым дополнительным фреймворком - person Ulrich Stark; 05.02.2021

Пытаться

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>

person Kamil Kiełczewski    schedule 15.06.2020

Вы можете сделать вызов AJAX (вероятно, используя библиотеку, такую ​​как Prototype.js или JQuery). AJAX может обрабатывать параметры как GET, так и POST.

person Diodeus - James MacFarlane    schedule 25.09.2008
comment
Использование XMLHttpRequest не направляет браузер на другую страницу. - person Jonny Buchanan; 25.09.2008