Pregunta

Estoy tratando de dirigir un navegador a una página diferente. Si quisiera una solicitud GET, podría decir

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

Pero el recurso al que intento acceder no responderá correctamente a menos que use una solicitud POST. Si esto no se generó dinámicamente, podría usar el HTML

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

Entonces simplemente enviaría el formulario desde el DOM.

Pero realmente me gustaría un código JavaScript que me permita decir

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

¿Cuál es la mejor implementación de navegador cruzado?

Editar

Lo siento, no estaba claro. Necesito una solución que cambie la ubicación del navegador, al igual que enviar un formulario. Si esto es posible con XMLHttpRequest , no es obvio. Y esto no debe ser asíncrono, ni usar XML, por lo que Ajax no es la respuesta.

¿Fue útil?

Solución

Cree dinámicamente <input> s en un formulario y envíelo

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

Ejemplo:

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

EDITAR : Dado que esto se ha votado demasiado, supongo que la gente va a copiar esto mucho. Así que agregué la verificación hasOwnProperty para corregir cualquier error inadvertido.

Otros consejos

Esta sería una versión de la respuesta seleccionada 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();
}

Una implementación simple y rápida de la respuesta de @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();

Por supuesto, debería usar un marco de JavaScript como Prototype o jQuery ...

Usando la función createElement proporcionada en esta respuesta , que es necesaria debido a La ruptura de IE con el atributo de nombre en elementos creados normalmente con 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);
}

La respuesta de Rakesh Pai es sorprendente, pero Hay un problema que ocurre para mí (en Safari ) cuando intento publicar un formulario con un campo llamado submit. Por ejemplo, post_to_url("http://google.com/",{ submit: "submit" } );. He parcheado ligeramente la función para caminar alrededor de esta colisión espacial variable.

    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. No puede hacer que la solicitud de publicación de JavaScript se envíe como un formulario.

Lo que puede tener es un formulario en HTML, luego envíelo con JavaScript. (como se explica muchas veces en esta página).

Puede crear el HTML usted mismo, no necesita JavaScript para escribir el HTML. Eso sería una tontería si la gente sugiriera eso.

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

Su función simplemente configuraría el formulario de la manera que lo desee.

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

Luego, úsalo como.

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

Pero simplemente dejaría de lado la función y simplemente lo haría.

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

Finalmente, la decisión de estilo va en el archivo ccs.

#ninja{ 
  display:none;
}

Personalmente, creo que los formularios deben abordarse por nombre, pero eso no es importante en este momento.

Si tiene Prototype , puede ajustar el código para generar y enviar el formulario oculto de esta manera:

 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 es la respuesta de rakesh, pero con soporte para matrices (que es bastante común en los formularios):

Javascript simple:

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, y aquí está la versión de jquery: (código ligeramente diferente, pero se reduce a lo mismo)

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

Una solución es generar el formulario y enviarlo. Una implementación es

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

Entonces puedo implementar un marcador de acortamiento de URL con un simple

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

Bueno, desearía haber leído todas las otras publicaciones para no perder tiempo creando esto a partir de la respuesta de Rakesh Pai. Aquí hay una solución recursiva que funciona con matrices y objetos. Sin dependencia de jQuery.

Se agregó un segmento para manejar casos en los que todo el formulario debe enviarse como una matriz. (es decir, donde no hay un objeto contenedor alrededor de una lista de elementos)

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

Tres opciones aquí.

  1. Respuesta estándar de JavaScript: ¡Use un marco! La mayoría de los frameworks de Ajax te habrán abstraído de una manera fácil de hacer una XMLHTTPRequest POST.

  2. Realice la solicitud XMLHTTPRequest usted mismo, pasando la publicación al método abierto en lugar de get. (Más información en Uso del método POST en XMLHTTPRequest (Ajax) .)

  3. A través de JavaScript, cree dinámicamente un formulario, agregue una acción, agregue sus entradas y envíe eso.

Iría por la ruta Ajax como otros sugirieron con 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");

Así es como lo escribí usando jQuery. Probado en Firefox e Internet & Nbsp; 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();
}

La forma más fácil es usar Ajax Post Request:

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

donde:

  • los datos son un objeto
  • dataType son los datos esperados por el servidor (xml, json, script, texto, html)
  • url es la dirección de su servidor RESt o cualquier función en el lado del servidor que acepte HTTP-POST.

Luego, en el controlador de éxito, redirija el navegador con algo como window.location.

La Prototype incluye un objeto Hashtable, con un " .toQueryString () " , que le permite convertir fácilmente un objeto / estructura de JavaScript en una cadena de estilo de cadena de consulta. Como la publicación requiere & Quot; body & Quot; de la solicitud para ser una cadena con formato de cadena de consulta, esto permite que su solicitud de Ajax funcione correctamente como una publicación. Aquí hay un ejemplo 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();
};

Esto funciona perfectamente en mi caso:

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

Puede usarlo en funciones como:

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

Con esto, puede publicar todos los valores de las entradas.

FormObject es una opción. Pero FormObject no es compatible con la mayoría de los navegadores ahora.

Sin embargo, otra solución recursiva , ya que algunas otras parecen estar rotas (no las probé todas). Este depende de lodash 3.x y ES6 ( jQuery no requerido):

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

Mi solución codificará objetos profundamente anidados, a diferencia de la solución actualmente aceptada por @RakeshPai.

Utiliza la biblioteca npm 'qs' y su función stringify para convertir objetos anidados en parámetros.

Este código funciona bien con un back-end de Rails, aunque debería poder modificarlo para que funcione con cualquier backend que necesite modificando las opciones pasadas a stringify. Rails requiere que arrayFormat se establezca en & Quot; brackets & Quot ;.

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

Ejemplo:

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

Produce estos parámetros de 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"]}]}

Esto es como la opción 2 de Alan (arriba). Cómo instanciar el httpobj se deja como ejercicio.

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

Esto se basa en el código de beauSD usando jQuery. Se mejora para que funcione de forma recursiva en los 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();
}

Puede agregar dinámicamente el formulario usando DHTML y luego enviarlo.

Puede usar una biblioteca como jQuery y su método $ .post .

Utilizo el document.forms java y lo repito para obtener todos los elementos en el formulario, luego lo envío a través de xhttp. Así que esta es mi solución para el envío de javascript / ajax (con todos los html incluidos como ejemplo):

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

El método que uso para publicar y dirigir a un usuario automáticamente a otra página es simplemente escribir un formulario oculto y luego enviarlo automáticamente. Tenga la seguridad de que la forma oculta no ocupa absolutamente ningún espacio en la página web. El código sería algo como esto:

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

Solicitud de envío automático

Una aplicación de envío automático estaría dirigiendo valores de formulario que el usuario coloca automáticamente en la otra página de regreso a esa página. Tal aplicación sería así:

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

Así es como lo hago.

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

Plugin jQuery para redirigir con POST o GET:

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

Para probar, incluya el archivo .js anterior o copie / pegue la clase en su código, luego use el código aquí, reemplazando " args " con sus nombres de variables y " valores " con los valores de esas variables respectivas:

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

Podría utilizar el método de activación jQuery para enviar el formulario, al igual que presiona un botón, así,

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

se enviará en el navegador.

Puede realizar una llamada AJAX (probablemente utilizando una biblioteca como Prototype.js o JQuery). AJAX puede manejar las opciones GET y POST.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top