Pergunta

Eu estou tentando direcionar um navegador para uma página diferente. Se eu quisesse um pedido GET, eu poderia dizer

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

Mas o recurso que eu estou tentando acessar não vai responder adequadamente a menos que eu usar uma solicitação POST. Se isso não fosse gerado dinamicamente, eu poderia usar o HTML

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

Em seguida, gostaria apenas de enviar o formulário a partir do DOM.

Mas realmente gostaria de código JavaScript que me permite dizer

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

Qual é a melhor implementação do navegador cruz?

Editar

Me desculpe, eu não estava clara. Eu preciso de uma solução que muda a localização do navegador, assim como a apresentação de um formulário. Se isso é possível com XMLHttpRequest , não é óbvio. E isso não deve ser assíncrono, nem o uso de XML, de modo que Ajax não é a resposta.

Foi útil?

Solução

dinamicamente criar <input>s em um formulário e enviá-lo

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

Exemplo:

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

Editar : Uma vez que este tem obtido upvoted tanto, eu estou supondo que as pessoas estarão muito isso colando cópia. Então eu adicionei a verificação hasOwnProperty para corrigir todos os erros inadvertidos.

Outras dicas

Esta seria uma versão da resposta selecionada usando 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();
}

A simples implementação rápida e suja de resposta @ 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();

É claro, você deveria usar um framework JavaScript, como Prototype ou jQuery ...

Usando a função createElement fornecido em esta resposta , que é necessária devido a quebrantamento do IE com o atributo nome em elementos criados normalmente com 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);
}

O Rakesh Pai resposta é incrível, mas existe um problema que ocorre para mim (em Safari ) quando tento postar um formulário com um campo chamado submit. Por exemplo, post_to_url("http://google.com/",{ submit: "submit" } );. Eu ter corrigido a função ligeiramente para passear essa colisão espaço variável.

    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!

No. Você não pode ter o pedido de pós JavaScript como um formulário de envio.

O que você pode ter é uma forma em HTML, em seguida, submetê-lo com o JavaScript. (Como explicado muitas vezes desta página).

Você pode criar o HTML, você não precisa ter o JavaScript para escrever o HTML. Isso seria bobo se as pessoas sugeriram que.

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

A sua função seria apenas configurar o formulário do jeito que você quiser.

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

Em seguida, usá-lo como.

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

Mas gostaria apenas de deixar de fora a função e apenas fazer.

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

Finalmente, a decisão estilo vai no arquivo CCS.

#ninja{ 
  display:none;
}

Pessoalmente acho que os formulários devem ser abordadas pelo nome, mas isso não é importante agora.

Se você tiver Prototype instalado, você pode apertar o código para gerar e enviar o formulário oculto como este:

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

Esta é a resposta de Rakesh, mas com suporte para matrizes (que é bastante comum em formulários):

javascript simples:

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, e aqui está a versão jQuery: (código ligeiramente diferente, mas resume-se a mesma coisa)

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

Uma solução é para gerar o formulário e enviá-lo. Uma implementação é

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

Para que eu possa implementar um encurtamento de URL bookmarklet com um simples

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

Bem, desejo que eu tinha lido todos os outros lugares, então eu fiz o tempo não perder criar este de resposta de Rakesh Pai. Aqui está uma solução recursiva que trabalha com matrizes e objetos. Sem dependência do jQuery.

Adicionado um segmento para lidar com casos onde o formulário inteiro devem ser apresentadas como um array. (Ie., Onde não há nenhum objeto de invólucro em torno de uma lista de itens)

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

Opções três aqui.

  1. Padrão JavaScript resposta: Use um quadro! frameworks mais Ajax terá abstraída uma maneira fácil de fazer um XMLHTTPRequest POST.

  2. Faça o pedido XMLHTTPRequest-se, passando de pós para o método aberto, em vez de get. (Mais informações em Usando o método POST em XMLHTTPRequest (Ajax) .)

  3. Via JavaScript, criar dinamicamente um formulário, adicionar uma ação, adicionar suas entradas, e alegam que.

eu ir abaixo da rota Ajax como outros sugeriram com algo como:

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

Aqui está como eu o escrevi usando jQuery. Testado no Firefox e 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();
}

A maneira mais fácil é usar Ajax Publicar Pedido:

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

Onde:

  • dados é um objeto
  • dataType são os dados esperado pelo servidor (xml, json, roteiro, texto, html)
  • url é o endereço do servidor de descanso ou qualquer função no lado do servidor que aceita o HTTP-POST.

Em seguida, no manipulador de sucesso redirecionar o navegador com algo como window.location.

O Prototype biblioteca inclui um objeto Hashtable, com um ".toQueryString) (" método , que lhe permite transformar facilmente um objeto / estrutura de JavaScript em uma string estilo query-string. Desde o cargo requer o "corpo" do pedido para ser uma string de consulta-string formatado, isso permite que o seu pedido Ajax para funcionar corretamente como um post. Aqui está um exemplo usando 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();
};

Isso funciona perfeitamente no meu caso:

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

Você pode usá-lo em função do tipo:

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

Usando isso, você pode adicionar todos os valores de entradas.

FormObject é uma opção. Mas FormObject não é suportado pela maioria dos navegadores agora.

No entanto, outra recursiva solução, uma vez que alguns dos outros parecem estar quebrado (eu não testar todos eles). Este depende lodash 3.x e ES6 ( jQuery não obrigatório):

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

A minha solução vai codificar objetos profundamente aninhadas, ao contrário da solução actualmente aceite por @RakeshPai.

Ele usa biblioteca npm dos qs 'e sua função stringify para converter objetos aninhados em parâmetros.

Esse código funciona bem com um backend Rails, embora você deve ser capaz de modificá-lo para trabalhar com qualquer backend que você precisa, modificando as opções passadas para stringify. Rails exige que arrayFormat ser definido como "suportes".

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

Exemplo:

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

produz esses parâmetros 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"]}]}

Isto é como opção 2 do Alan (acima). Como instanciar o httpobj é deixado como um exercício.

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

Este é baseado no código do beauSD usando jQuery. É melhorada para que ele funciona de forma recursiva em objetos.

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

Você pode adicionar dinamicamente o formulário utilizando DHTML e, em seguida, submeter-se.

Você pode usar uma biblioteca como jQuery e sua $ .post método .

Eu uso o java document.forms e loop-lo para obter todos os elementos no formulário, em seguida, enviar via xhttp. Portanto, esta é a minha solução para javascript / ajax enviar (com todo html incluído como um exemplo):

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

O método que eu uso para postar e direcionar um usuário automaticamente para outra página é apenas para escrever uma forma escondida e depois auto apresentá-lo. Tenha certeza de que a forma escondida leva absolutamente nenhum espaço na página web. O código seria algo parecido com isto:

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

Aplicação de auto submeter

Uma aplicação de um automóvel submete estaria dirigindo valores de forma que o usuário automaticamente colocar em por outro página de volta para essa página. Um tal pedido seria assim:

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

Aqui está como eu fazê-lo.

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

jQuery plugin para o redirecionamento com POST ou GET:

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

Para teste, incluir o arquivo js acima ou copiar / colar a classe em seu código, em seguida, usar o código aqui, substituindo "args" com seus nomes de variáveis, e "valores" com os valores dessas respectivas variáveis:

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

Você poderia você método gatilho jQuery para enviar o formulário, assim como você pressionar um botão, como assim,

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

apresentará no navegador.

Você pode fazer uma chamada de AJAX (provavelmente usando uma biblioteca como o uso de Prototype.js ou JQuery). AJAX pode lidar com ambas as opções GET e POST.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top