JavaScript пост запрос как форма отправить - PullRequest
1388 голосов
/ 25 сентября 2008

Я пытаюсь направить браузер на другую страницу. Если бы я хотел запрос 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 не является ответом.

Ответы [ 29 ]

1998 голосов
/ 25 сентября 2008

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

/**
 * 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 paramiters 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 wordy 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, чтобы исправить любые непреднамеренные ошибки.

118 голосов
/ 04 апреля 2011

Это будет версия выбранного ответа с использованием 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();
}
64 голосов
/ 25 сентября 2008

Простая и быстрая реализация ответа @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 ...

51 голосов
/ 25 сентября 2008

Использование функции createElement, предоставленной в этом ответе , что необходимо из-за поломки IE с атрибутом имени для элементов, созданных обычно с 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);
}
37 голосов
/ 16 июля 2010

Ответ Ракеш Пая удивителен, но у меня возникает проблема (в 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!
29 голосов
/ 19 августа 2013

Нет. У вас не может быть запроса на публикацию 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;
}

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

24 голосов
/ 24 января 2009

Если у вас установлен 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();
22 голосов
/ 22 марта 2012

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

обычный 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(); 
}
15 голосов
/ 28 января 2014

Что ж, жаль, что я не прочитал все остальные посты, чтобы не терять время на создание этого из ответа Ракеш Пая Вот рекурсивное решение, которое работает с массивами и объектами. Нет зависимости от 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();
};
15 голосов
/ 25 сентября 2008

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

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});
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...