web-dev-qa-db-fra.com

formulaire sérialiser javascript (pas de framework)

Vous vous demandez s'il y a une fonction en javascript sans jquery ou un framework qui me permet de sérialiser le formulaire et d'accéder à la version sérialisée?

100
RussellHarrower

La bibliothèque miniature from-serialize ne repose pas sur un framework. En dehors de cela, vous devrez implémenter vous-même la fonction de sérialisation. (bien que d'un poids de 1,2 kilo-octets, pourquoi ne pas l'utiliser?)

29
Lusitanian

Voici l'approche pure JavaScript:

var form = document.querySelector('form');
var data = new FormData(form);
var req = new XMLHttpRequest();
req.send(data);

Bien que cela ne semble fonctionner que pour les demandes POST.

https://developer.mozilla.org/en-US/docs/Web/API/FormData

129
Artur Beljajev

Si vous ciblez les navigateurs qui prennent en charge le constructeur URLSearchParams ( les navigateurs les plus récents ) et le constructeur FormData(formElement) (navigateurs récents à l'exception de Edge), utilisez ceci:

new URLSearchParams(new FormData(formElement)).toString()

Pour les navigateurs qui supportent URLSearchParams mais pas le constructeur FormData(formElement), utilisez this FormData polyfill et:

new URLSearchParams(Array.from(new FormData(formElement))).toString()

Pour les navigateurs plus anciens (par exemple, IE 10), utilisez le polyfill FormData , un Array.from si nécessaire, et ce code unique:

Array.from(new FormData(formElement), e => e.map(encodeURIComponent).join('=')).join('&')
46
glebm
function serialize (form) {
    if (!form || form.nodeName !== "FORM") {
            return;
    }
    var i, j, q = [];
    for (i = form.elements.length - 1; i >= 0; i = i - 1) {
        if (form.elements[i].name === "") {
            continue;
        }
        switch (form.elements[i].nodeName) {
            case 'INPUT':
                switch (form.elements[i].type) {
                    case 'text':
                    case 'tel':
                    case 'email':
                    case 'hidden':
                    case 'password':
                    case 'button':
                    case 'reset':
                    case 'submit':
                        q.Push(form.elements[i].name + "=" + encodeURIComponent(form.elements[i].value));
                        break;
                    case 'checkbox':
                    case 'radio':
                        if (form.elements[i].checked) {
                                q.Push(form.elements[i].name + "=" + encodeURIComponent(form.elements[i].value));
                        }                                               
                        break;
                }
                break;
                case 'file':
                break; 
            case 'TEXTAREA':
                    q.Push(form.elements[i].name + "=" + encodeURIComponent(form.elements[i].value));
                    break;
            case 'SELECT':
                switch (form.elements[i].type) {
                    case 'select-one':
                        q.Push(form.elements[i].name + "=" + encodeURIComponent(form.elements[i].value));
                        break;
                    case 'select-multiple':
                        for (j = form.elements[i].options.length - 1; j >= 0; j = j - 1) {
                            if (form.elements[i].options[j].selected) {
                                    q.Push(form.elements[i].name + "=" + encodeURIComponent(form.elements[i].options[j].value));
                            }
                        }
                        break;
                }
                break;
            case 'BUTTON':
                switch (form.elements[i].type) {
                    case 'reset':
                    case 'submit':
                    case 'button':
                        q.Push(form.elements[i].name + "=" + encodeURIComponent(form.elements[i].value));
                        break;
                }
                break;
            }
        }
    return q.join("&");
}

Source: http://code.google.com/p/form-serialize/source/browse/trunk/serialize-0.1.js

32
Johndave Decano

Voici une version légèrement modifiée de TibTibs ':

function serialize(form) {
    var field, s = [];
    if (typeof form == 'object' && form.nodeName == "FORM") {
        var len = form.elements.length;
        for (i=0; i<len; i++) {
            field = form.elements[i];
            if (field.name && !field.disabled && field.type != 'file' && field.type != 'reset' && field.type != 'submit' && field.type != 'button') {
                if (field.type == 'select-multiple') {
                    for (j=form.elements[i].options.length-1; j>=0; j--) {
                        if(field.options[j].selected)
                            s[s.length] = encodeURIComponent(field.name) + "=" + encodeURIComponent(field.options[j].value);
                    }
                } else if ((field.type != 'checkbox' && field.type != 'radio') || field.checked) {
                    s[s.length] = encodeURIComponent(field.name) + "=" + encodeURIComponent(field.value);
                }
            }
        }
    }
    return s.join('&').replace(/%20/g, '+');
}

Les champs désactivés sont ignorés et les noms sont également codés en URL. Le remplacement des expressions rationnelles de% 20 caractères n’est effectué qu’une fois, avant que la chaîne ne soit renvoyée.

La chaîne de requête a la même forme que le résultat de la méthode $ .serialize () de jQuery.

23

J'ai commencé avec la réponse de Johndave Decano.

Cela devrait résoudre quelques-uns des problèmes mentionnés dans les réponses à sa fonction.

  1. Remplacez% 20 par un symbole +.
  2. Les types Envoyer/Bouton ne seront soumis que s’ils ont été cliqués pour soumettre le formulaire.
  3. Les boutons de réinitialisation seront ignorés.
  4. Le code m'a semblé superflu car il fait essentiellement la même chose, quels que soient les types de champs. Sans parler de l'incompatibilité de Avec les types de champs HTML5 tels que 'tel' et 'email', J'ai donc supprimé la plupart des détails avec les instructions switch.

Les types de boutons seront toujours ignorés s'ils n'ont pas de valeur de nom.

function serialize(form, evt){
    var evt    = evt || window.event;
    evt.target = evt.target || evt.srcElement || null;
    var field, query='';
    if(typeof form == 'object' && form.nodeName == "FORM"){
        for(i=form.elements.length-1; i>=0; i--){
            field = form.elements[i];
            if(field.name && field.type != 'file' && field.type != 'reset'){
                if(field.type == 'select-multiple'){
                    for(j=form.elements[i].options.length-1; j>=0; j--){
                        if(field.options[j].selected){
                            query += '&' + field.name + "=" + encodeURIComponent(field.options[j].value).replace(/%20/g,'+');
                        }
                    }
                }
                else{
                    if((field.type != 'submit' && field.type != 'button') || evt.target == field){
                        if((field.type != 'checkbox' && field.type != 'radio') || field.checked){
                            query += '&' + field.name + "=" + encodeURIComponent(field.value).replace(/%20/g,'+');
                        }   
                    }
                }
            }
        }
    }
    return query.substr(1);
}

C'est ainsi que j'utilise actuellement cette fonction.

<form onsubmit="myAjax('http://example.com/services/email.php', 'POST', serialize(this, event))">
10
TibTibs

Si vous devez envoyer le formulaire "myForm" en utilisant POST au format json, vous pouvez procéder comme suit:

const formEntries = new FormData(myForm).entries();
const json = Object.assign(...Array.from(formEntries, ([x,y]) => ({[x]:y})));
fetch('/api/foo', {
  method: 'POST',
  body: JSON.stringify(json)
});

La deuxième ligne convertit un tableau comme:

[["firstProp", "firstValue"], ["secondProp", "secondValue"], ...and so on... ]

... dans un objet régulier, comme:

{"firstProp": "firstValue", "secondProp": "secondValue", ...and so on ... }

... il effectue cette conversion en passant un mapFn dans Array.from (). Ce mapFn est appliqué à chaque paire ["a", "b"] et les convertit en {"a": "b"} de sorte que le tableau contienne beaucoup d'objets avec une seule propriété. MapFn utilise la "déstructuration" pour obtenir les noms des première et deuxième parties de la paire, et utilise également un "ComputedPropertyName" ES6 pour définir le nom de la propriété dans l'objet renvoyé par mapFn (c'est pourquoi " x]: quelque chose "plutôt que simplement" x: quelque chose ".

Tous ces objets de propriété uniques sont ensuite passés dans les arguments de la fonction Object.assign () qui fusionne tous les objets de propriété uniques en un seul objet comportant toutes les propriétés.

Array.from (): https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/from

Destructuration des paramètres: https://simonsmith.io/destructuring-objects-as-function-parameters-in-es6/

Plus d'informations sur les noms de propriété calculés ici: Variable comme nom de propriété dans un objet littéral JavaScript?

9
molsson

Fonctionne dans tous les navigateurs.

function formSerialize(formElement) {
  const values = {};
  const inputs = formElement.elements;

  for (let i = 0; i < inputs.length; i++) {
    values[inputs[i].name] = inputs[i].value;
  }
  return values;
}

const r = formSerialize(document.querySelector('form'));

console.log(r);
console.log(JSON.stringify(r));
<form action="/my-handling-form-page" method="post">
  <div>
    <label for="name">Name:</label>
    <input type="text" id="name" name="user_name" value="John">
  </div>
  <div>
    <label for="mail">E-mail:</label>
    <input type="email" id="mail" name="user_mail" value="[email protected]">
  </div>
  <div>
    <label for="msg">Message:</label>
    <textarea id="msg" name="user_message">Hello My Friend</textarea>
  </div>
</form>

7
David Lemon
HTMLElement.prototype.serialize = function(){
    var obj = {};
    var elements = this.querySelectorAll( "input, select, textarea" );
    for( var i = 0; i < elements.length; ++i ) {
        var element = elements[i];
        var name = element.name;
        var value = element.value;

        if( name ) {
            obj[ name ] = value;
        }
    }
    return JSON.stringify( obj );
}

Pour utiliser comme ceci:

var dataToSend = document.querySelector("form").serialize();

J'espère avoir aidé.

5
Eduardo Borges

Une version refactorisée du code de @ SimonSteinberger utilisant moins de variables et tirant parti de la vitesse des boucles forEach (qui sont un peu plus rapides que fors)

function serialize(form) {
    var result = [];
    if (typeof form === 'object' && form.nodeName === 'FORM')
        Array.prototype.slice.call(form.elements).forEach(function(control) {
            if (
                control.name && 
                !control.disabled && 
                ['file', 'reset', 'submit', 'button'].indexOf(control.type) === -1
            )
                if (control.type === 'select-multiple')
                    Array.prototype.slice.call(control.options).forEach(function(option) {
                        if (option.selected) 
                            result.Push(encodeURIComponent(control.name) + '=' + encodeURIComponent(option.value));
                    });
                else if (
                    ['checkbox', 'radio'].indexOf(control.type) === -1 || 
                    control.checked
                ) result.Push(encodeURIComponent(control.name) + '=' + encodeURIComponent(control.value));
        });
        return result.join('&').replace(/%20/g, '+');
}
5
Stefan Gabos

Si vous souhaitez sérialiser les entrées d'un événement. Voici une approche JavaScript pure que j'utilise.

// serialize form
var data = {};
var inputs = [].slice.call(e.target.getElementsByTagName('input'));
inputs.forEach(input => {
  data[input.name] = input.value;
});

Les données seront un objet JavaScript des entrées.

4
CAOakley

J'ai repensé TibTibs pour répondre à quelque chose de beaucoup plus clair à lire. C'est un peu plus long à cause de la largeur de 80 caractères et de quelques commentaires.

En outre, il ignore les noms de champs vides et les valeurs vides.

// Serialize the specified form into a query string.
//
// Returns a blank string if +form+ is not actually a form element.
function $serialize(form, evt) {
  if(typeof(form) !== 'object' && form.nodeName !== "FORM")
    return '';

  var evt    = evt || window.event || { target: null };
  evt.target = evt.target || evt.srcElement || null;
  var field, query = '';

  // Transform a form field into a query-string-friendly
  // serialized form.
  //
  // [NOTE]: Replaces blank spaces from its standard '%20' representation
  //         into the non-standard (though widely used) '+'.
  var encode = function(field, name) {
    if (field.disabled) return '';

    return '&' + (name || field.name) + '=' +
           encodeURIComponent(field.value).replace(/%20/g,'+');
  }

  // Fields without names can't be serialized.
  var hasName = function(el) {
    return (el.name && el.name.length > 0)
  }

  // Ignore the usual suspects: file inputs, reset buttons,
  // buttons that did not submit the form and unchecked
  // radio buttons and checkboxes.
  var ignorableField = function(el, evt) {
    return ((el.type == 'file' || el.type == 'reset')
        || ((el.type == 'submit' || el.type == 'button') && evt.target != el)
        || ((el.type == 'checkbox' || el.type == 'radio') && !el.checked))
  }

  var parseMultiSelect = function(field) {
    var q = '';

    for (var j=field.options.length-1; j>=0; j--) {
      if (field.options[j].selected) {
        q += encode(field.options[j], field.name);
      }
    }

    return q;
  };

  for(i = form.elements.length - 1; i >= 0; i--) {
    field = form.elements[i];

    if (!hasName(field) || field.value == '' || ignorableField(field, evt))
      continue;

    query += (field.type == 'select-multiple') ? parseMultiSelect(field)
                                               : encode(field);
  }

  return (query.length == 0) ? '' : query.substr(1);
}
3
Brian Edmonds

J'ai récupéré la méthode entries () de formData à @moison answer et à MDN il est dit que

La méthode FormData.entries () retourne un itérateur permettant d'aller à travers toutes les paires clé/valeur contenues dans cet objet. La clé de chaque paire est un objet USVString; la valeur soit un USVString, ou un Blob.

mais le seul problème est que le navigateur mobile (Android et Safari ne sont pas pris en charge) et IE et le bureau Safari 

mais fondamentalement voici mon approche:

let theForm =  document.getElementById("contact"); 

theForm.onsubmit = function(event) {
    event.preventDefault();

    let rawData = new FormData(theForm);
    let data = {};

   for(let pair of rawData.entries()) {
     data[pair[0]] = pair[1]; 
    }
    let contactData = JSON.stringify(data);
    console.warn(contactData);
    //here you can send a post request with content-type :'application.json'

};

le code peut être trouvé ici

1
Espoir Murhabazi
  // supports IE8 and IE9 
  function serialize(form) {
    var inputs = form.elements;
    var array = [];
    for(i=0; i < inputs.length; i++) {
      var inputNameValue = inputs[i].name + '=' + inputs[i].value;
      array.Push(inputNameValue);
    }
    return array.join('&');
  }
 //using the serialize function written above
 var form = document.getElementById("form");//get the id of your form. i am assuming the id to be named form.
 var form_data = serialize(form);
 var xhr = new XMLHttpRequest();
 xhr.send(form_data);

 //does not work with IE8 AND IE9
 var form = document.querySelector('form');
 var data = new FormData(form);
 var xhr = new XMLHttpRequest();
 xhr.send(data);
1
Onome Mine Adamu

L'utilisation de la fonction de réduction JavaScript devrait faire l'affaire pour tous les navigateurs, y compris IE9>:

Array.prototype.slice.call(form.elements) // convert form elements to array
    .reduce(function(acc,cur){   // reduce 
        var o = {type : cur.type, name : cur.name, value : cur.value}; // get needed keys
        if(['checkbox','radio'].indexOf(cur.type) !==-1){o.checked = cur.checked;} // if input is checkbox or radio type
        acc.Push(o);
        return acc;
 },[]);

Exemple live ci-dessous.

var _formId = document.getElementById('formId'),
    formData = Array.prototype.slice.call(_formId.elements).reduce(function(acc,cur,indx,arr){
        var o = {type : cur.type, name : cur.name, value : cur.value};
            if(['checkbox','radio'].indexOf(cur.type) !==-1){o.checked = cur.checked;}
            acc.Push(o);
            return acc;
        },[]);
        
// view
document.getElementById('formOutput').innerHTML = JSON.stringify(formData, null, 4)
<form id="formId">
    <input type="text" name="texttype" value="some text">
    <select>
        <option value="Opt 1">Opt 1</option>
        <option value="Opt 2" selected>Opt 2</option>
        <option value="Opt 3">Opt 3</option>
    </select>
    <input type="checkbox" name="checkboxtype" value="Checkbox 1" checked> Checkbox 1
    <input type="checkbox" name="checkboxtype" value="Checkbox 2"> Checkbox 2
    <input type="radio" name="radiotype" value="Radio Btn 1"> Radio Btn 1
    <input type="radio" name="radiotype" value="Radio Btn 2" checked> Radio Btn 2
</form>
<pre><code id="formOutput"></code></pre>
0
crashtestxxx

Je pourrais être fou mais je trouve ces réponses sérieusement bouffies. Voici ma solution

function serialiseForm(form) {
  var input = form.getElementsByTagName("input");
  var formData = {};
  for (var i = 0; i < input.length; i++) {
    formData[input[i].name] = input[i].value;
  }
  return formData = JSON.stringify(formData);
}
0

J'espère que ça va marcher

var serializeForm = (formElement) => {
  const formData = {};
  const inputs = formElement.elements;

  for (let i = 0; i < inputs.length; i++) {
    if(inputs[i].name!=="")
        formData[inputs[i].name] = inputs[i].value;
  }
  return formData;
}
0
Manoj Rana
document.serializeForm = function (selector) {
     var dictionary = {};
     var form = document.querySelector(selector);
     var formdata = new FormData(form);
     var done = false;
     var iterator = formdata.entries();
     do {
         var prop = iterator.next();
         if (prop.done && !prop.value) {
             done = true;
         }
         else {
             dictionary[prop.value[0]] = prop.value[1];
         }

     } while (!done);
     return dictionary;
}
0
Hasan

À des fins de débogage, cela pourrait vous aider:

function print_form_data(form) {
    const form_data = new FormData(form);

    for (const item of form_data.entries()) {
        console.log(item);
    }

    return false;
}
0
tobias47n9e