web-dev-qa-db-fra.com

Un moyen plus simple de transformer FormData en chaîne de requête

J'envoie une POST via XMLHttpRequest avec des données saisies dans un formulaire HTML. Le formulaire sans interférence de JavaScript soumettrait ses données codées comme application/x-www-form-urlencoded.

Avec XMLHttpRequest, je voulais envoyer les données avec via l'API FormData qui ne fonctionne pas car il traite les données comme si elles étaient codées comme multipart/form-data. Pour cela, j'ai besoin d'écrire les données sous la forme d'une chaîne de requête, correctement échappée, dans la méthode d'envoi du XMLHttpRequest.

addEntryForm.addEventListener('submit', function(event) {
    // Gather form data
    var formData = new FormData(this);
    // Array to store the stringified and encoded key-value-pairs.
    var parameters = []
    for (var pair of formData.entries()) {
        parameters.Push(
            encodeURIComponent(pair[0]) + '=' +
            encodeURIComponent(pair[1])
        );
    }

    var httpRequest = new XMLHttpRequest();
    httpRequest.open(form.method, form.action);

    httpRequest.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');

    httpRequest.onreadystatechange = function() {
        if (httpRequest.readyState === XMLHttpRequest.DONE) {
            if (httpRequest.status === 200) {
                console.log('Successfully submitted the request');
            } else {
                console.log('Error while submitting the request');
            }
        }
    };

    httpRequest.send(parameters.join('&'));

    // Prevent submitting the form via regular request
    event.preventDefault();
});

Maintenant, tout cela avec le for ... of loop, etc. semble un peu compliqué. Existe-t-il un moyen plus simple de transformer FormData en une chaîne de requête? Ou puis-je envoyer en quelque sorte FormData avec un encodage différent?

9
kleinfreund

Vous pouvez utiliser RLSearchParams

const queryString = new URLSearchParams(new FormData(myForm)).toString()
29
Hans

Vous avez demandé une solution plus simple ...
Une boucle for est le moyen le plus simple de parcourir une collection - à mon humble avis.

Mais il existe une version plus courte si vous utilisez le opérateur de propagation/syntaxe (...)

La syntaxe étendue permet à une expression d'être développée dans des endroits où plusieurs arguments (pour les appels de fonction) ou plusieurs éléments (pour les littéraux de tableau) ou plusieurs variables (pour l'affectation de la déstructuration) sont attendus.

Votre for...of la boucle peut alors être remplacée par:

let parameters = [...formData.entries()] // expand the elements from the .entries() iterator into an actual array
                     .map(e => encodeURIComponent(e[0]) + "=" + encodeURIComponent(e[1]))  // transform the elements into encoded key-value-pairs
7
Andreas

Si vous pouviez utiliser JQuery, vous appelleriez simplement la fonction .serialize() sur votre objet form, comme suit:

function getQueryString() {
  var str = $( "form" ).serialize();
  console.log(str);
}

$( "#cmdTest" ).on( "click", getQueryString );
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<form>
  <select name="list1">
    <option>opt1</option>
    <option>opt2</option>
  </select>
 
  <br>
  <input type="text" name="txt1" value="valWith%Special&Char$">
  <br>
  <input type="checkbox" name="check" value="check1" id="ch1">
  <label for="ch1">check1</label>
  <input type="checkbox" name="check" value="check2" checked="checked" id="ch2">
  <label for="ch2">check2</label>
 
  <br>
  <input type="radio" name="radio" value="radio1" checked="checked" id="r1">
  <label for="r1">radio1</label>
  <input type="radio" name="radio" value="radio2" id="r2">
  <label for="r2">radio2</label>
</form>
  
<button id="cmdTest">Get queryString</button>

Remarque: il encode également les données pour les utiliser dans la demande d'URL

J'espère que cela vous aide, au revoir.

3
Alessandro