Comment créer une chaîne de requête avec Javascript

Réponses:

-25

J'ai essayé de chercher une réponse à cette question il y a quelque temps, mais j'ai fini par écrire ma propre fonction qui extrait les valeurs du formulaire.

ce n'est pas parfait mais cela correspond à mes besoins.

function form_params( form )
{
    var params = new Array()
    var length = form.elements.length
    for( var i = 0; i < length; i++ )
    {
        element = form.elements[i]

        if(element.tagName == 'TEXTAREA' )
        {
            params[element.name] = element.value
        }
        else if( element.tagName == 'INPUT' )
        {
            if( element.type == 'text' || element.type == 'hidden' || element.type == 'password')
            {
                params[element.name] = element.value
            }
            else if( element.type == 'radio' && element.checked )
            {
                if( !element.value )
                    params[element.name] = "on"
                else
                    params[element.name] = element.value

            }
            else if( element.type == 'checkbox' && element.checked )
            {
                if( !element.value )
                    params[element.name] = "on"
                else
                    params[element.name] = element.value
            }
        }
    }
    return params;
}

form_params renvoie un mappage (clé -> valeur) des paramètres. l'entrée est l'élément de formulaire (élément DOM)

Il ne gère pas les champs permettant une sélection multiple.

hasen
la source
44
Est-ce juste moi ou est-ce que cela ne répond pas du tout à la question? Il demandait une chaîne de requête, pas un tableau mappé.
Jake Wilson
2
@JakeWilson Oui, cette réponse ne répond qu'à moitié à la question. Le tableau doit toujours entrer dans un format de chaîne de requête.
Hutch Moore
9
wow je devais être un noob chez JS à l'époque. Utilisation new Array()pour initialiser un dictionnaire. Mais là encore, le code semble beaucoup plus propre que certaines des conneries que j'écrirais ces jours-ci!
hasen
2
@hasen peut-être envisageriez-vous de modifier cette réponse ou, euh, eh bien, de la supprimer? Il a de plus en plus de votes négatifs à chaque fois que je fais défiler dessus = -D (je me souviens même de l'époque où il avait un rapport positif ...)
Klesun
1
@ArturKlesun oui, non. Je m'en fiche. Vous pouvez essayer de demander à la personne qui a posé la question de désaccepter cette réponse.
hasen
220

Mise à jour 2k20: utilisez la solution de Josh avec URLSearchParams.toString () .

Ancienne réponse:


Sans jQuery

var params = {
    parameter1: 'value_1',
    parameter2: 'value 2',
    parameter3: 'value&3' 
};

var esc = encodeURIComponent;
var query = Object.keys(params)
    .map(k => esc(k) + '=' + esc(params[k]))
    .join('&');

Pour les navigateurs qui ne prennent pas en charge la syntaxe de la fonction de flèche qui nécessite ES5, remplacez la .map...ligne par

    .map(function(k) {return esc(k) + '=' + esc(params[k]);})
Klesun
la source
8
La meilleure solution que j'ai encore vue - très propre et concise. Quelques mises en garde, cependant. 1) dans .map (), k et params [k] doivent être encodés, par exemple encodeURIComponent (k) et encodeURIComponent (params [k]). 2) Vous êtes autorisé à avoir plus d'une instance d'un paramètre nommé dans une chaîne de requête. Si vous voulez cette capacité, vous devrez utiliser un tableau au lieu d'un objet (la plupart des applications n'en auront pas besoin ou n'en auront pas besoin).
John Deighan
9
3) Tous les navigateurs ne prennent pas en charge la syntaxe de la fonction de flèche (qui nécessite ES5). Si vous souhaitez prendre en charge tous les navigateurs (et encoder les parties), remplacez le .map () ci-dessus par .map (function (k) {return encodeURIComponent (k) + '=' + encodeURIComponent (params [k]);})
John Deighan
1
Belle. Vraiment magnifique.
Mikko Ohtamaa
9
"pas assez de jquery"
Eugene Pankov
1
@ user1738579 J'ai modifié la réponse pour inclure également votre exemple pour les non-ES5.
Taylor Edmiston
135

Si vous utilisez jQuery, vous voudrez peut-être consulter jQuery.param() http://api.jquery.com/jQuery.param/

Exemple:

var params = {
    parameter1: 'value1',
    parameter2: 'value2',
    parameter3: 'value3' 
};
var query = $.param(params);
document.write(query);
Klemen Tušar
la source
13
C'est en fait la bonne réponse! La chaîne de requête d'un formulaire est $.param($('#myform').serializeArray()).
Jesse
7
@Jesse, ce serait le même résultat que:$('#myform').serialize()
couperet
95
jQuery !== JavaScript
gphilip
14
@gphilip Eh bien, c'est pourquoi j'ai commencé la réponse par "Si vous utilisez jQuery ...". Sinon, si vous souhaitez l'implémenter dans vanilla JS, vous pouvez examiner l'implémentation de jQuery.param()ici github.com/jquery/jquery/blob/master/src/serialize.js :)
Klemen Tušar
2
Contrairement à ma réponse, celui-ci prend en charge les objets imbriqués commesomeStr=value1&someObj[a]=5&someObj[b]=6&someArr[]=1&someArr[]=2
Klesun
113

L'API URLSearchParams est disponible dans tous les navigateurs modernes. Par exemple:

const params = new URLSearchParams({
  var1: "value",
  var2: "value2",
  arr: "foo",
});
console.log(params.toString());
//Prints "var1=value&var2=value2&arr=foo"

Josh
la source
3
Meilleure réponse ici imo. Juste pour y ajouter, vous pouvez le faire params.append(key, value)plus tard pour ajouter de nouveaux paramètres de recherche dans des scénarios plus compliqués.
Mingwei Zhang
4
Notez que les valeurs non définies et nulles sont incluses dans la chaîne finale:x=null&y=undefined
pomber
2
En outre, si vous avez déjà un objet URL (par exemple const url = new URL("https://stackoverflow.com")), vous pouvez définir ses chaînes de requête url.search = new URLSearchParams({foo: "bar"})ouurl.searchParams.append("foo", "bar")
Miguel Pynto
Notez que TS vous avertira de l'utilisation d'un objet simple, mais cela fonctionne néanmoins très bien
Vadorequest
@pomber Avez-vous de bonnes idées pour filtrer ces éléments non définis?
Dan Gayle
53

Cela ne répond pas directement à votre question, mais voici une fonction générique qui créera une URL contenant des paramètres de chaîne de requête. Les paramètres (noms et valeurs) sont échappés en toute sécurité pour être inclus dans une URL.

function buildUrl(url, parameters){
  var qs = "";
  for(var key in parameters) {
    var value = parameters[key];
    qs += encodeURIComponent(key) + "=" + encodeURIComponent(value) + "&";
  }
  if (qs.length > 0){
    qs = qs.substring(0, qs.length-1); //chop off last "&"
    url = url + "?" + qs;
  }
  return url;
}

// example:
var url = "http://example.com/";

var parameters = {
  name: "George Washington",
  dob: "17320222"
};

console.log(buildUrl(url, parameters));
// => http://www.example.com/?name=George%20Washington&dob=17320222
Michael
la source
1
Existe-t-il une fonction intégrée similaire à celle-ci dans l'un des frameworks javascript populaires comme jquery, mootools, etc ...?
Samuel
Une solution JavaScript native plus robuste est disponible sur stackoverflow.com/a/1714899/1269037
Dan Dascalescu
L'implémentation la plus étrange jamais créée, pourquoi avez-vous besoin d'initialiser new Arraypendant que vous l'utilisez réellement comme objet? o, O
Umut Sirin
@UmutSirin Lol ouais je ne savais pas grand chose sur Javascript à l'époque. xD Je pense que je le traitais comme un tableau PHP. N'hésitez pas à refactoriser si vous le souhaitez.
Michael
@Michael Haha, ouais. Je viens d'envoyer une modification. Merci pour la réponse!
Umut Sirin le
22

Avec jQuery, vous pouvez le faire en $.param

$.param({ action: 'ship', order_id: 123, fees: ['f1', 'f2'], 'label': 'a demo' })

// -> "action=ship&order_id=123&fees%5B%5D=f1&fees%5B%5D=f2&label=a+demo"
manish_s
la source
17

ES2017 (ES8)

Faire usage de Object.entries(), qui renvoie un tableau de [key, value]paires d'objets . Par exemple, car {a: 1, b: 2}il reviendrait [['a', 1], ['b', 2]]. Il n'est pas pris en charge (et ne le sera pas) uniquement par IE.

Code:

const buildURLQuery = obj =>
      Object.entries(obj)
            .map(pair => pair.map(encodeURIComponent).join('='))
            .join('&');

Exemple:

buildURLQuery({name: 'John', gender: 'male'});

Résultat:

"name=John&gender=male"
Przemek
la source
Faire usage de url.spec.whatwg.org/#urlsearchparams au lieu
Boris
10

Non, je ne pense pas que JavaScript standard ait cela intégré, mais Prototype JS a cette fonction (sûrement la plupart des autres frameworks JS en ont aussi, mais je ne les connais pas), ils l'appellent sérialiser .

Je peux recommander Prototype JS, cela fonctionne assez bien. Le seul inconvénient que j'ai vraiment remarqué c'est sa taille (quelques centaines de ko) et sa portée (beaucoup de code pour ajax, dom, etc.). Ainsi, si vous ne voulez qu'un sérialiseur de formulaires, c'est exagéré, et à proprement parler si vous ne voulez que la fonctionnalité Ajax (qui est principalement ce pour quoi je l'ai utilisé), c'est exagéré. À moins que vous ne soyez prudent, vous constaterez peut-être qu'il fait un peu trop de «magie» (comme étendre chaque élément dom qu'il touche avec les fonctions Prototype JS juste pour trouver des éléments), ce qui ralentit les cas extrêmes.

Stein G. Strindhaug
la source
Je me demande juste s'il y a quelque chose de intégré. On dirait qu'il devrait y en avoir. Je déteste le prototype, mais je ne vous en veux pas :)
Lorsque JavaScript a été conçu, Ajax n'a pas encore été découvert, donc analyser un formulaire juste pour obtenir la chaîne de requête (qu'il créerait lui-même une fois soumis) n'avait probablement pas beaucoup de sens. Aujourd'hui c'est le cas, difficile ... Btw, comparé à script.aculo.us, le prototype est sympa . :)
Stein G.Strindhaug
10

querystring peut vous aider.

Afin que vous puissiez

const querystring = require('querystring')

url += '?' + querystring.stringify(parameters)
ImLeo
la source
3
Pour les applications frontales,
Robert Pankowecki
@RobertPankowecki, oui, qs c'est mieux et déjà dans mon arsenal, bravo!
ImLeo
6

Si vous ne souhaitez pas utiliser de bibliothèque, cela devrait couvrir la plupart / tous les mêmes types d'éléments de formulaire.

function serialize(form) {
  if (!form || !form.elements) return;

  var serial = [], i, j, first;
  var add = function (name, value) {
    serial.push(encodeURIComponent(name) + '=' + encodeURIComponent(value));
  }

  var elems = form.elements;
  for (i = 0; i < elems.length; i += 1, first = false) {
    if (elems[i].name.length > 0) { /* don't include unnamed elements */
      switch (elems[i].type) {
        case 'select-one': first = true;
        case 'select-multiple':
          for (j = 0; j < elems[i].options.length; j += 1)
            if (elems[i].options[j].selected) {
              add(elems[i].name, elems[i].options[j].value);
              if (first) break; /* stop searching for select-one */
            }
          break;
        case 'checkbox':
        case 'radio': if (!elems[i].checked) break; /* else continue */
        default: add(elems[i].name, elems[i].value); break;
      }
    }
  }

  return serial.join('&');
}
Jonathan Lonowski
la source
Merci! J'étais juste confronté au même problème que l'affiche originale, et votre fonction était exactement ce dont j'avais besoin.
dagw
4

Vous n'avez pas besoin d'un formulaire pour le faire avec Prototype. Utilisez simplement la fonction Object.toQueryString :

Object.toQueryString({ action: 'ship', order_id: 123, fees: ['f1', 'f2'], 'label': 'a demo' })

// -> 'action=ship&order_id=123&fees=f1&fees=f2&label=a%20demo'
Thibaut Barrère
la source
4
Certes, vous avez répondu il y a près de 10 ans, mais ce code est désormais obsolète.
SEoF
4

Vous pouvez le faire de nos jours avec FormDataet URLSearchParamssans avoir besoin de faire une boucle sur quoi que ce soit.

const formData = new FormData(form);
const searchParams = new URLSearchParams(formData);
const queryString = searchParams.toString();

Les navigateurs plus anciens auront cependant besoin d'un polyfill.

Björn Tantau
la source
3

Je ne suis pas tout à fait sûr moi-même, je me souviens avoir vu jQuery le faire dans une certaine mesure, mais il ne gère pas du tout les enregistrements hiérarchiques, et encore moins d'une manière conviviale php.

Une chose que je sais avec certitude, c'est que lorsque vous créez des URL et que vous collez le produit dans le dom, n'utilisez pas simplement du string-glue pour le faire, ou vous vous ouvrirez à un sauteur de page pratique.

Par exemple, certains logiciels publicitaires incorporent la chaîne de version de tout ce qui exécute votre flash. C'est bien quand sa chaîne simple générique adobe, mais cependant, c'est très naïf, et explose dans un désordre embarrassant pour les personnes qui ont installé Gnash, car la chaîne de version de gnash se trouve contenir une licence de droit d'auteur GPL complète, avec des URL et <a href> balises. En utilisant cela dans votre générateur d'annonceurs string-glue, la page s'ouvre et le HTML déséquilibré apparaît dans le dom.

La morale de l'histoire:

   var foo = document.createElement("elementnamehere"); 
   foo.attribute = allUserSpecifiedDataConsideredDangerousHere; 
   somenode.appendChild(foo); 

Ne pas:

   document.write("<elementnamehere attribute=\"" 
        + ilovebrokenwebsites 
        + "\">" 
        + stringdata 
        + "</elementnamehere>");

Google doit apprendre cette astuce. J'ai essayé de signaler le problème, ils semblent s'en moquer.

Kent Fredric
la source
Droit dessus. Document.write est tellement 1995, de toute façon.
2

Comme le dit Stein, vous pouvez utiliser la bibliothèque prototype javascript de http://www.prototypejs.org . Incluez le JS et c'est très simple alors, $('formName').serialize()vous retournerez ce que vous voulez!

Shyam
la source
2

Peut-être un peu redondant mais le moyen le plus propre que j'ai trouvé qui s'appuie sur certaines des réponses ici:

const params: {
   key1: 'value1',
   key2: 'value2',
   key3: 'value3',
}

const esc = encodeURIComponent;
const query = Object.keys(params)
  .map(k => esc(k) + '=' + esc(params[k]))
  .join('&');

return fetch('my-url', {
  method: 'POST',
  headers: {'Content-Type': 'application/x-www-form-urlencoded'},
  body: query,
})

La source

David Pascoal
la source
1

Ces réponses sont très utiles, mais je veux ajouter une autre réponse, qui peut vous aider à créer une URL complète. Cela peut vous aider concat de base url, path, hashet parameters.

var url = buildUrl('http://mywebsite.com', {
        path: 'about',
        hash: 'contact',
        queryParams: {
            'var1': 'value',
            'var2': 'value2',
            'arr[]' : 'foo'
        }
    });
    console.log(url);

Vous pouvez télécharger via npm https://www.npmjs.com/package/build-url

Démo:

;(function () {
  'use strict';

  var root = this;
  var previousBuildUrl = root.buildUrl;

  var buildUrl = function (url, options) {
    var queryString = [];
    var key;
    var builtUrl;
    var caseChange; 
    
    // 'lowerCase' parameter default = false,  
    if (options && options.lowerCase) {
        caseChange = !!options.lowerCase;
    } else {
        caseChange = false;
    }

    if (url === null) {
      builtUrl = '';
    } else if (typeof(url) === 'object') {
      builtUrl = '';
      options = url;
    } else {
      builtUrl = url;
    }

    if(builtUrl && builtUrl[builtUrl.length - 1] === '/') {
      builtUrl = builtUrl.slice(0, -1);
    } 

    if (options) {
      if (options.path) {
          var localVar = String(options.path).trim(); 
          if (caseChange) {
            localVar = localVar.toLowerCase();
          }
          if (localVar.indexOf('/') === 0) {
              builtUrl += localVar;
          } else {
            builtUrl += '/' + localVar;
          }
      }

      if (options.queryParams) {
        for (key in options.queryParams) {
          if (options.queryParams.hasOwnProperty(key) && options.queryParams[key] !== void 0) {
            var encodedParam;
            if (options.disableCSV && Array.isArray(options.queryParams[key]) && options.queryParams[key].length) {
              for(var i = 0; i < options.queryParams[key].length; i++) {
                encodedParam = encodeURIComponent(String(options.queryParams[key][i]).trim());
                queryString.push(key + '=' + encodedParam);
              }
            } else {              
              if (caseChange) {
                encodedParam = encodeURIComponent(String(options.queryParams[key]).trim().toLowerCase());
              }
              else {
                encodedParam = encodeURIComponent(String(options.queryParams[key]).trim());
              }
              queryString.push(key + '=' + encodedParam);
            }
          }
        }
        builtUrl += '?' + queryString.join('&');
      }

      if (options.hash) {
        if(caseChange)
            builtUrl += '#' + String(options.hash).trim().toLowerCase();
        else
            builtUrl += '#' + String(options.hash).trim();
      }
    } 
    return builtUrl;
  };

  buildUrl.noConflict = function () {
    root.buildUrl = previousBuildUrl;
    return buildUrl;
  };

  if (typeof(exports) !== 'undefined') {
    if (typeof(module) !== 'undefined' && module.exports) {
      exports = module.exports = buildUrl;
    }
    exports.buildUrl = buildUrl;
  } else {
    root.buildUrl = buildUrl;
  }
}).call(this);


var url = buildUrl('http://mywebsite.com', {
		path: 'about',
		hash: 'contact',
		queryParams: {
			'var1': 'value',
			'var2': 'value2',
			'arr[]' : 'foo'
		}
	});
	console.log(url);

Hien Nguyen
la source
1

Je sais que c'est une réponse très tardive mais fonctionne très bien ...

var obj = {
a:"a",
b:"b"
}

Object.entries(obj).map(([key, val])=>`${key}=${val}`).join("&");

note: object.entries renverra la clé, les paires de valeurs

la sortie de la ligne ci-dessus sera a = a & b = b

J'espère que ça aide quelqu'un.

Codage heureux ...

ajaykumar mp
la source
0

Il est probablement trop tard pour répondre à votre question.
J'avais la même question et je n'aimais pas continuer à ajouter des chaînes pour créer une URL. J'ai donc commencé à utiliser $ .param comme l' explique techhouse .
J'ai également trouvé une bibliothèque URI.js qui crée facilement les URL pour vous. Il y a plusieurs exemples qui vous aideront à : URI.js Documentation .
Voici l'un d'entre eux:

var uri = new URI("?hello=world");
uri.setSearch("hello", "mars"); // returns the URI instance for chaining
// uri == "?hello=mars"

uri.setSearch({ foo: "bar", goodbye : ["world", "mars"] });
// uri == "?hello=mars&foo=bar&goodbye=world&goodbye=mars"

uri.setSearch("goodbye", "sun");
// uri == "?hello=mars&foo=bar&goodbye=sun"

// CAUTION: beware of arrays, the following are not quite the same
// If you're dealing with PHP, you probably want the latter…
uri.setSearch("foo", ["bar", "baz"]);
uri.setSearch("foo[]", ["bar", "baz"]);`
SaraNa
la source
0

var params = { width:1680, height:1050 };
var str = jQuery.param( params );

console.log(str)
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

Bashirpour
la source