Domanda

Sto cercando di indirizzare un browser verso una pagina diversa. Se volessi una richiesta GET, potrei dire

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

Ma la risorsa a cui sto tentando di accedere non risponderà correttamente se non utilizzo una richiesta POST. Se questo non fosse generato dinamicamente, potrei usare l'HTML

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

Quindi vorrei solo inviare il modulo dal DOM.

Ma davvero vorrei il codice JavaScript che mi permettesse di dire

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

Qual è la migliore implementazione cross browser?

Modifica

Mi dispiace non essere stato chiaro. Ho bisogno di una soluzione che cambi la posizione del browser, proprio come l'invio di un modulo. Se questo è possibile con XMLHttpRequest , non è ovvio. E questo non dovrebbe essere asincrono, né usare XML, quindi Ajax non è la risposta.

È stato utile?

Soluzione

Crea dinamicamente <input> s in un modulo e invialo

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

Esempio:

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

MODIFICA : poiché questo è stato votato così tanto, suppongo che le persone lo copieranno molto. Quindi ho aggiunto il segno di spunta hasOwnProperty per correggere eventuali bug involontari.

Altri suggerimenti

Questa sarebbe una versione della risposta selezionata 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 semplice e rapida implementazione della risposta @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();

Ovviamente, dovresti usare un framework JavaScript come Prototype o jQuery ...

Uso della funzione createElement fornita in questa risposta , necessaria a causa di Rottura di IE con l'attributo name su elementi creati 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 risposta di Rakesh Pai è sorprendente, ma c'è un problema che si presenta per me (in Safari ) quando provo a postare un modulo con un campo chiamato submit. Ad esempio, post_to_url("http://google.com/",{ submit: "submit" } );. Ho modificato leggermente la funzione per aggirare questa collisione di spazio variabile.

    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. Non puoi avere la richiesta di post JavaScript come l'invio di un modulo.

Quello che puoi avere è un modulo in HTML, quindi inviarlo con JavaScript. (come spiegato più volte in questa pagina).

Puoi creare tu stesso l'HTML, non è necessario JavaScript per scrivere l'HTML. Sarebbe sciocco se la gente lo suggerisse.

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

La tua funzione configurerebbe semplicemente il modulo nel modo desiderato.

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

Quindi, usalo come.

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

Ma vorrei semplicemente lasciare la funzione e farlo.

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

Infine, la decisione sullo stile va nel file ccs.

#ninja{ 
  display:none;
}

Personalmente penso che i moduli dovrebbero essere indirizzati per nome, ma al momento non è importante.

Se hai Prototype , puoi restringere il codice per generare e inviare il modulo nascosto in questo modo:

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

questa è la risposta di rakesh, ma con il supporto per gli array (che è abbastanza comune nelle forme):

javascript semplice:

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, ed ecco la versione jquery: (codice leggermente diverso, ma si riduce alla stessa cosa)

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 soluzione è generare il modulo e inviarlo. Un'implementazione è

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

Quindi posso implementare un bookmarklet che accorcia gli URL con un semplice

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

Beh, vorrei aver letto tutti gli altri post in modo da non perdere tempo a crearlo dalla risposta di Rakesh Pai. Ecco una soluzione ricorsiva che funziona con matrici e oggetti. Nessuna dipendenza da jQuery.

Aggiunto un segmento per gestire i casi in cui l'intero modulo deve essere inviato come un array. (ovvero dove non esiste alcun oggetto wrapper attorno a un elenco di elementi)

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

Tre opzioni qui.

  1. Risposta JavaScript standard: usa un framework! La maggior parte dei framework Ajax ti ha estratto un modo semplice per creare un XMLHTTPRequest POST.

  2. Effettua tu stesso la richiesta XMLHTTPRequest, passando la posta nel metodo aperto anziché get. (Ulteriori informazioni in Uso del metodo POST in XMLHTTPRequest (Ajax) .)

  3. Tramite JavaScript, crea dinamicamente un modulo, aggiungi un'azione, aggiungi i tuoi input e invialo.

Vorrei seguire la strada dell'Ajax come altri hanno suggerito con qualcosa del tipo:

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

Ecco come l'ho scritto usando jQuery. Testato su 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();
}

Il modo più semplice è utilizzare Ajax Post Request:

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

dove:

  • i dati sono un oggetto
  • dataType sono i dati previsti dal server (xml, json, script, text, html)
  • url è l'indirizzo del server RESt o di qualsiasi funzione sul lato server che accetta HTTP-POST.

Quindi nel gestore del successo reindirizzare il browser con qualcosa come window.location.

La libreria Prototype include un oggetto Hashtable, con un " .toQueryString & () quot; metodo, che consente di trasformare facilmente un oggetto / struttura JavaScript in una stringa di stile stringa di query. Poiché il post richiede il & Quot; body & Quot; della richiesta di essere una stringa formattata con stringa di query, ciò consente alla tua richiesta Ajax di funzionare correttamente come post. Ecco un esempio 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();
};

Questo funziona perfettamente nel mio caso:

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

Puoi usarlo in funzione come:

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

Usando questo puoi pubblicare tutti i valori degli input.

FormObject è un'opzione. Ma FormObject non è supportato dalla maggior parte dei browser ora.

Ancora un'altra soluzione ricorsiva , poiché alcuni altri sembrano essere rotti (non li ho testati tutti). Questo dipende da lodash 3.x e ES6 ( jQuery non richiesto):

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

La mia soluzione codificherà oggetti profondamente nidificati, a differenza della soluzione attualmente accettata da @RakeshPai.

Utilizza la libreria npm 'qs' e la sua funzione stringify per convertire oggetti nidificati in parametri.

Questo codice funziona bene con un back-end di Rails, anche se dovresti essere in grado di modificarlo per funzionare con qualsiasi backend di cui hai bisogno modificando le opzioni passate per stringify. Rails richiede che arrayFormat sia impostato su & Quot; parentesi & 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();
}

Esempio:

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 questi parametri di 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"]}]}

È come l'opzione 2 di Alan (sopra). Come creare un'istanza di httpobj è lasciato come esercizio.

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

Questo si basa sul codice di beauSD usando jQuery. È stato migliorato e funziona in modo ricorsivo sugli oggetti.

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

È possibile aggiungere dinamicamente il modulo utilizzando DHTML e quindi inviare.

Puoi utilizzare una libreria come jQuery e il suo $ .post method .

Uso document.forms java e lo eseguo in loop per ottenere tutti gli elementi nel modulo, quindi invio tramite xhttp. Quindi questa è la mia soluzione per javascript / ajax submit (con tutti gli html inclusi come esempio):

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

Il metodo che uso per pubblicare e indirizzare automaticamente un utente su un'altra pagina è semplicemente scrivere un modulo nascosto e quindi inviarlo automaticamente. Assicurati che il modulo nascosto non occupi assolutamente spazio sulla pagina web. Il codice sarebbe simile a questo:

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

Richiesta di invio automatico

Un'applicazione di un invio automatico reindirizzerà i valori dei moduli che l'utente inserirà automaticamente nell'altra pagina di nuovo a quella pagina. Tale applicazione sarebbe così:

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

Ecco come lo faccio.

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 per il reindirizzamento con POST o GET:

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

Per provare, includi il file .js sopra o copia / incolla la classe nel tuo codice, quindi usa il codice qui, sostituendo " args " con i nomi delle variabili e " valori " con i valori di quelle rispettive variabili:

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

Potresti utilizzare il metodo di trigger jQuery per inviare il modulo, proprio come quando premi un pulsante, in questo modo,

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

verrà inviato sul browser.

Potresti effettuare una chiamata AJAX (probabilmente usando una libreria come usare Prototype.js o JQuery). AJAX può gestire entrambe le opzioni GET e POST.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top