web-dev-qa-db-fra.com

Demande de publication JavaScript comme un formulaire à envoyer

J'essaie de diriger un navigateur vers une autre page. Si je voulais une demande GET, je pourrais dire

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

Mais la ressource à laquelle j'essaie d'accéder ne répondra pas correctement à moins d'utiliser une requête POST. Si cela n’était pas généré dynamiquement, je pourrais utiliser le code HTML

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

Ensuite, je voudrais simplement soumettre le formulaire à partir du DOM.

Mais vraiment, je voudrais un code JavaScript qui me permet de dire

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

Quelle est la meilleure implémentation multi-navigateurs?

Modifier 

Je suis désolé je n'ai pas été clair. J'ai besoin d'une solution qui modifie l'emplacement du navigateur, tout comme pour l'envoi d'un formulaire. Si cela est possible avec XMLHttpRequest , ce n'est pas évident. Et cela ne devrait pas être asynchrone, ni utiliser XML, donc Ajax n'est pas la solution.

1358
Joseph Holsten
 /**
 * 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) {
    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);

    for(var key in params) {
        if(params.hasOwnProperty(key)) {
            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();
}

Exemple:

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

EDIT: Comme cela a été tellement voté, j'imagine que les gens vont beaucoup copier-coller. J'ai donc ajouté le contrôle hasOwnProperty pour corriger les bugs involontaires.

1948
Rakesh Pai

Ce serait une version de la réponse sélectionnée en utilisant 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();
}
114
Ryan Delucchi

Une implémentation simple et rapide de la réponse @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();

Bien sûr, vous devriez plutôt utiliser un framework JavaScript tel que Prototype ou jQuery ...

64
Alexandre Victoor

Utilisation de la fonction createElement fournie dans this answer , nécessaire en raison de la fragmentation de IE avec l'attribut name sur les éléments créés normalement avec 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);
}
51
Jonny Buchanan

La réponse de Rakesh Pai est incroyable, mais un problème se produit pour moi (dans Safari ) lorsque j'essaie de publier un formulaire avec un champ appelé submit. Par exemple, post_to_url("http://google.com/",{ submit: "submit" } );. J'ai légèrement modifié la fonction pour contourner cette collision spatiale 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!
35
Kendall Hopkins

Non, vous ne pouvez pas avoir la demande de publication JavaScript comme un formulaire à envoyer.

Ce que vous pouvez avoir est un formulaire en HTML, puis soumettez-le avec JavaScript. (comme expliqué à plusieurs reprises sur cette page)

Vous pouvez créer le code HTML vous-même, vous n'avez pas besoin de JavaScript pour écrire le code HTML. Ce serait idiot si les gens le suggéraient.

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

Votre fonction configurerait simplement le formulaire comme vous le souhaitez.

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

Ensuite, utilisez-le comme.

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

Mais je voudrais juste laisser de côté la fonction et juste faire.

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

Enfin, la décision de style va dans le fichier ccs.

.ninja{ 
  display:none;
}

Personnellement, je pense que les formulaires doivent être nommés, mais ce n’est pas important pour le moment.

27
gaby de wilde

Si vous avez Prototype installé, vous pouvez resserrer le code pour générer et envoyer le formulaire masqué comme suit:

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

c'est la réponse de rakesh, mais avec le support des tableaux (ce qui est assez courant dans les formulaires): 

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, et voici la version jquery: (code légèrement différent, mais se résume à la même chose)

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

Si seulement j'avais lu tous les autres posts, je n'ai donc pas perdu de temps à créer ceci grâce à la réponse de Rakesh Pai. Voici une solution récursive qui fonctionne avec les tableaux et les objets. Aucune dépendance sur jQuery.

Ajout d'un segment pour gérer les cas où l'ensemble du formulaire doit être soumis comme un tableau. (c'est-à-dire s'il n'y a pas d'objet wrapper autour d'une liste d'éléments)

/**
 * 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
emragins

Une solution consiste à générer le formulaire et à le soumettre. Une mise en œuvre est

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

Je peux donc implémenter un bookmarklet de raccourcissement d'URL avec

javascript:post_to_url('http://is.Gd/create.php', {'URL': location.href});
14
Joseph Holsten

Trois options ici.

  1. Réponse JavaScript standard: Utilisez un cadre! La plupart des frameworks Ajax vous auront résumé un moyen simple de créer un XMLHTTPRequest POST.

  2. Faites la demande XMLHTTPRequest vous-même, en passant post dans la méthode open au lieu de get. (Plus d'informations dans Utilisation de la méthode POST dans XMLHTTPRequest (Ajax).)

  3. Via JavaScript, créez un formulaire de manière dynamique, ajoutez une action, ajoutez vos entrées et soumettez-le.

11
Alan Storm

Voici comment je l'ai écrit en utilisant jQuery. Testé dans Firefox et 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();
}
10
beauburrier

Je suivrais la route de l'Ajax comme d'autres l'avaient suggéré avec quelque chose comme:

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

Le moyen le plus simple consiste à utiliser Ajax Post Request:

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

où:

  • la donnée est un objet
  • dataType correspond aux données attendues par le serveur (xml, json, script, text, html) 
  • url est l'adresse de votre serveur RESt ou de toute fonction côté serveur qui accepte HTTP-POST.

Ensuite, dans le gestionnaire de succès, redirigez le navigateur avec quelque chose comme window.location.

6
JLavoie

La bibliothèque Prototype comprend un objet Hashtable, avec une méthode ".toQueryString ()", qui vous permet de transformer facilement un objet/une structure JavaScript en une chaîne de style de chaîne de requête. Étant donné que la publication requiert que le "corps" de la demande soit une chaîne formatée avec une chaîne de requête, cela permet à votre requête Ajax de fonctionner correctement en tant que publication. Voici un exemple utilisant 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();
};
5
Adam Ness

Cela fonctionne parfaitement dans mon cas:

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

Vous pouvez l'utiliser comme:

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

En utilisant cela, vous pouvez poster toutes les valeurs des entrées.

3
ChintanThummar

Ma solution va coder des objets profondément imbriqués, contrairement à la solution actuellement acceptée par @RakeshPai.

Il utilise la bibliothèque npm 'qs' et sa fonction stringify pour convertir des objets imbriqués en paramètres.

Ce code fonctionne bien avec un back-end Rails, bien que vous devriez pouvoir le modifier pour fonctionner avec tout le back-end dont vous avez besoin en modifiant les options passées à stringify. Rails nécessite que arrayFormat soit défini sur "parenthèses".

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

Exemple:

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

Produit ces paramètres 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"]}]}
2
cmrichards

Encore une autre solution récursive, car certaines d’autres semblent cassées (je ne les ai pas toutes testées). Celui-ci dépend de lodash 3.x et de ES6 (jQuery non requis):

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

Vous pouvez ajouter dynamiquement le formulaire à l'aide de DHTML, puis le soumettre.

1
AnthonyWJones

Vous pouvez utiliser une bibliothèque comme jQuery et sa méthode $ .post .

1
Bill Turner

J'utilise le document.forms Java et le boucle pour obtenir tous les éléments du formulaire, puis l'envoyer via xhttp. Voici donc ma solution pour javascript/ajax submit (avec tout le code HTML inclus à titre d'exemple):

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

Ceci est basé sur le code de beauSD utilisant jQuery. Il est amélioré pour fonctionner de manière récursive sur les objets.

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

C'est comme l'option 2 d'Alan (ci-dessus). Comment instancier le httpobj est laissé comme un exercice.

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

FormObject est une option. Mais FormObject n'est plus supporté par la plupart des navigateurs.

1
lingceng

La méthode que j'utilise pour envoyer et diriger automatiquement un utilisateur vers une autre page consiste à écrire un formulaire masqué, puis à le soumettre automatiquement. Soyez assuré que la forme masquée ne prend absolument aucun espace sur la page Web. Le code ressemblerait à ceci:

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

Application de soumission automatique

Une application de soumission automatique dirigerait les valeurs de formulaire que l'utilisateur inscrirait automatiquement sur l'autre page pour revenir à cette page. Une telle application serait comme ceci:

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

Voici comment je le fais.

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

plug-in jQuery pour la redirection avec POST ou GET:

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

Pour tester, incluez le fichier .js ci-dessus ou copiez/collez la classe dans votre code, puis utilisez le code ici, en remplaçant "args" par vos noms de variable et "valeurs" par les valeurs de ces variables:

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

Vous pouvez utiliser la méthode de déclenchement jQuery pour soumettre le formulaire, comme si vous appuyez sur un bouton,

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

il soumettra sur le navigateur.

0
Canaan Etai