Existe-t-il un moyen simple, d’une ligne, d’obtenir les données d’un formulaire comme si le formulaire était soumis uniquement au format HTML classique?
Par exemple, dans:
<form>
<input type="radio" name="foo" value="1" checked="checked" />
<input type="radio" name="foo" value="0" />
<input name="bar" value="xxx" />
<select name="this">
<option value="hi" selected="selected">Hi</option>
<option value="ho">Ho</option>
</form>
En dehors:
{
"foo": "1",
"bar": "xxx",
"this": "hi"
}
Quelque chose comme cela est trop simple, car cela n'inclut pas (correctement) les zones de texte, les sélections, les boutons radio et les cases à cocher:
$("#form input").each(function() {
data[theFieldName] = theFieldValue;
});
$('form').serialize() //this produces: "foo=1&bar=xxx&this=hi"
Utilisez $('form').serializeArray()
, qui retourne un tableau :
[
{"name":"foo","value":"1"},
{"name":"bar","value":"xxx"},
{"name":"this","value":"hi"}
]
Une autre option est $('form').serialize()
, qui renvoie une chaîne :
"foo=1&bar=xxx&this=hi"
Jetez un oeil à cette démo jsfiddle
Réponse mise à jour pour 2014: HTML5 FormData le fait
var formData = new FormData(document.querySelector('form'))
Vous pouvez ensuite poster formData exactement tel qu'il est: il contient tous les noms et toutes les valeurs utilisés dans le formulaire.
Basé sur jQuery.serializeArray
, renvoie les paires clé-valeur.
var data = $('#form').serializeArray().reduce(function(obj, item) {
obj[item.name] = item.value;
return obj;
}, {});
document.querySelector('form').addEventListener('submit', (e) => {
const formData = new FormData(e.target);
// Now you can use formData.get('foo'), for example.
// Don't forget e.preventDefault() if you want to stop normal form .submission
});
Ceci est une réponse tatillonne, mais laissez-moi vous expliquer pourquoi c'est une meilleure solution:
Nous traitons correctement un formulaire de soumission plutôt que d'appuyer sur un bouton. Certaines personnes aiment pousser entrer sur les champs. Certaines personnes utilisent d'autres périphériques de saisie tels que la saisie vocale ou d'autres dispositifs d'accessibilité. Manipulez le formulaire et soumettez-le correctement pour tout le monde.
Nous creusons dans les données de formulaire pour le formulaire réel qui a été soumis. Si vous modifiez votre sélecteur de formulaire ultérieurement, vous n'avez pas à modifier les sélecteurs pour tous les champs. De plus, vous pouvez avoir plusieurs formulaires avec les mêmes noms d’entrée. Pas besoin de distinguer des identifiants excessifs ou non, il suffit de suivre les entrées en fonction du formulaire soumis. Cela vous permet également d'utiliser un seul gestionnaire d'événements pour plusieurs formulaires if adapté à votre situation.
L’interface FormData est relativement nouvelle, mais elle est bien supportée par les navigateurs. C'est un excellent moyen de construire cette collection de données pour obtenir les vraies valeurs du contenu du formulaire. Sans cela, vous devrez parcourir tous les éléments (comme avec form.elements
) et déterminer ce qui est coché, ce qui ne l’est pas, quelles sont les valeurs, etc. Totalement possible si vous avez besoin d’un ancien support de navigateur, mais L’interface FormData est plus simple.
J'utilise ES6 ici ... ce n'est pas une obligation, changez-le pour qu'il soit compatible avec ES5 si vous avez besoin d'une ancienne prise en charge de navigateur.
utilisez .serializeArray () pour obtenir les données au format tableau, puis convertissez-les en objet:
function getFormObj(formId) {
var formObj = {};
var inputs = $('#'+formId).serializeArray();
$.each(inputs, function (i, input) {
formObj[input.name] = input.value;
});
return formObj;
}
Voici une solution très simple et courte qui ne nécessite même pas Jquery.
var formElements=document.getElementById("myForm").elements;
var postData={};
for (var i=0; i<formElements.length; i++)
if (formElements[i].type!="submit")//we dont want to include the submit-buttom
postData[formElements[i].name]=formElements[i].value;
$('#myform').serialize();
$("#form input, #form select, #form textarea").each(function() {
data[theFieldName] = theFieldValue;
});
en dehors de cela, vous pouvez regarder serialize () ;
J'utilise ceci:
plugin jQuery
(function($){
$.fn.getFormData = function(){
var data = {};
var dataArray = $(this).serializeArray();
for(var i=0;i<dataArray.length;i++){
data[dataArray[i].name] = dataArray[i].value;
}
return data;
}
})(jQuery);
formulaire HTML
<form id='myform'>
<input name='myVar1' />
<input name='myVar2' />
</form>
Obtenir les données
var myData = $("#myForm").getFormData();
Voici une implémentation JavaScript uniquement fonctionnelle qui gère correctement les cases à cocher, les boutons radio et les curseurs (probablement d'autres types de saisie également, mais je n'ai fait que les tester).
function setOrPush(target, val) {
var result = val;
if (target) {
result = [target];
result.Push(val);
}
return result;
}
function getFormResults(formElement) {
var formElements = formElement.elements;
var formParams = {};
var i = 0;
var elem = null;
for (i = 0; i < formElements.length; i += 1) {
elem = formElements[i];
switch (elem.type) {
case 'submit':
break;
case 'radio':
if (elem.checked) {
formParams[elem.name] = elem.value;
}
break;
case 'checkbox':
if (elem.checked) {
formParams[elem.name] = setOrPush(formParams[elem.name], elem.value);
}
break;
default:
formParams[elem.name] = setOrPush(formParams[elem.name], elem.value);
}
}
return formParams;
}
function setOrPush(target, val) {
var result = val;
if (target) {
result = [target];
result.Push(val);
}
return result;
}
function getFormResults(formElement) {
var formElements = formElement.elements;
var formParams = {};
var i = 0;
var elem = null;
for (i = 0; i < formElements.length; i += 1) {
elem = formElements[i];
switch (elem.type) {
case 'submit':
break;
case 'radio':
if (elem.checked) {
formParams[elem.name] = elem.value;
}
break;
case 'checkbox':
if (elem.checked) {
formParams[elem.name] = setOrPush(formParams[elem.name], elem.value);
}
break;
default:
formParams[elem.name] = setOrPush(formParams[elem.name], elem.value);
}
}
return formParams;
}
//
// Boilerplate for running the snippet/form
//
function ok() {
var params = getFormResults(document.getElementById('main_form'));
document.getElementById('results_wrapper').innerHTML = JSON.stringify(params, null, ' ');
}
(function() {
var main_form = document.getElementById('main_form');
main_form.addEventListener('submit', function(event) {
event.preventDefault();
ok();
}, false);
})();
<form id="main_form">
<div id="questions_wrapper">
<p>what is a?</p>
<div>
<input type="radio" required="" name="q_0" value="a" id="a_0">
<label for="a_0">a</label>
<input type="radio" required="" name="q_0" value="b" id="a_1">
<label for="a_1">b</label>
<input type="radio" required="" name="q_0" value="c" id="a_2">
<label for="a_2">c</label>
<input type="radio" required="" name="q_0" value="d" id="a_3">
<label for="a_3">d</label>
</div>
<div class="question range">
<label for="a_13">A?</label>
<input type="range" required="" name="q_3" id="a_13" min="0" max="10" step="1" list="q_3_dl">
<datalist id="q_3_dl">
<option value="0"></option>
<option value="1"></option>
<option value="2"></option>
<option value="3"></option>
<option value="4"></option>
<option value="5"></option>
<option value="6"></option>
<option value="7"></option>
<option value="8"></option>
<option value="9"></option>
<option value="10"></option>
</datalist>
</div>
<p>A and/or B?</p>
<div>
<input type="checkbox" name="q_4" value="A" id="a_14">
<label for="a_14">A</label>
<input type="checkbox" name="q_4" value="B" id="a_15">
<label for="a_15">B</label>
</div>
</div>
<button id="btn" type="submit">OK</button>
</form>
<div id="results_wrapper"></div>
Si vous recherchez une mise en œuvre plus complète, jetez un coup d'œil à cette section du projet pour laquelle j'ai conçu ceci . Je mettrai éventuellement à jour cette question avec la solution complète que j'ai proposée, mais cela aidera peut-être quelqu'un.
Si vous utilisez jQuery, voici une petite fonction qui fera ce que vous cherchez.
Commencez par ajouter un identifiant à votre formulaire (sauf s’il s’agit du seul formulaire de la page, vous pouvez simplement utiliser "formulaire" comme requête dom).
<form id="some-form">
<input type="radio" name="foo" value="1" checked="checked" />
<input type="radio" name="foo" value="0" />
<input name="bar" value="xxx" />
<select name="this">
<option value="hi" selected="selected">Hi</option>
<option value="ho">Ho</option>
</form>
<script>
//read in a form's data and convert it to a key:value object
function getFormData(dom_query){
var out = {};
var s_data = $(dom_query).serializeArray();
//transform into simple data/value object
for(var i = 0; i<s_data.length; i++){
var record = s_data[i];
out[record.name] = record.value;
}
return out;
}
console.log(getFormData('#some-form'));
</script>
La sortie ressemblerait à ceci:
{
"foo": "1",
"bar": "xxx",
"this": "hi"
}
Nous sommes en 2019 et il existe un meilleur moyen de le faire:
const form = document.querySelector('form');
const data = new URLSearchParams(new FormData(form).entries());
ou si vous voulez un objet simple à la place
const form = document.querySelector('form');
const data = Object.fromEntries(new FormData(form).entries());
notez toutefois que cela ne fonctionnera pas avec les clés en double comme dans les cases à cocher à sélections multiples et en double avec le même nom.
Vous pouvez également utiliser les FormData Objects; L'objet FormData vous permet de compiler un ensemble de paires clé/valeur à envoyer à l'aide de XMLHttpRequest. Il est principalement destiné à être utilisé pour l'envoi de données de formulaire, mais peut être utilisé indépendamment des formulaires afin de transmettre des données à clé.
var formElement = document.getElementById("myform_id");
var formData = new FormData(formElement);
console.log(formData);
var formData = new FormData($('#form-id'));
params = $('#form-id').serializeArray();
$.each(params, function(i, val) {
formData.append(val.name, val.value);
});
J'ai inclus la réponse pour rendre également l'objet requis.
function getFormData(form) {
var rawJson = form.serializeArray();
var model = {};
$.map(rawJson, function (n, i) {
model[n['name']] = n['value'];
});
return model;
}
Ceci ajoutera tous les champs de formulaire à l'objet JavaScript "res":
var res = {};
$("#form input, #form select, #form textarea").each(function(i, obj) {
res[obj.name] = $(obj).val();
})
vous pouvez utiliser cette fonction pour avoir un objet ou un JSON de forme.
pour l'utiliser:
var object = formService.getObjectFormFields("#idform");
function getObjectFormFields(formSelector)
{
/// <summary>Função que retorna objeto com base nas propriedades name dos elementos do formulário.</summary>
/// <param name="formSelector" type="String">Seletor do formulário</param>
var form = $(formSelector);
var result = {};
var arrayAuxiliar = [];
form.find(":input:text").each(function (index, element)
{
var name = $(element).attr('name');
var value = $(element).val();
result[name] = value;
});
form.find(":input[type=hidden]").each(function (index, element)
{
var name = $(element).attr('name');
var value = $(element).val();
result[name] = value;
});
form.find(":input:checked").each(function (index, element)
{
var name;
var value;
if ($(this).attr("type") == "radio")
{
name = $(element).attr('name');
value = $(element).val();
result[name] = value;
}
else if ($(this).attr("type") == "checkbox")
{
name = $(element).attr('name');
value = $(element).val();
if (result[name])
{
if (Array.isArray(result[name]))
{
result[name].Push(value);
} else
{
var aux = result[name];
result[name] = [];
result[name].Push(aux);
result[name].Push(value);
}
} else
{
result[name] = [];
result[name].Push(value);
}
}
});
form.find("select option:selected").each(function (index, element)
{
var name = $(element).parent().attr('name');
var value = $(element).val();
result[name] = value;
});
arrayAuxiliar = [];
form.find("checkbox:checked").each(function (index, element)
{
var name = $(element).attr('name');
var value = $(element).val();
result[name] = arrayAuxiliar.Push(value);
});
form.find("textarea").each(function (index, element)
{
var name = $(element).attr('name');
var value = $(element).val();
result[name] = value;
});
return result;
}
Sur la base de la réponse de neuront, j'ai créé une méthode JQuery simple qui récupère les données de formulaire sous forme de paires clé-valeur, mais fonctionne pour les sélections multiples et les entrées de tableau avec le nom = 'exemple []'.
Voici comment cela est utilisé:
var form_data = $("#form").getFormObject();
Vous trouverez ci-dessous un exemple de sa définition et de son fonctionnement.
// Function start
$.fn.getFormObject = function() {
var object = $(this).serializeArray().reduce(function(obj, item) {
var name = item.name.replace("[]", "");
if ( typeof obj[name] !== "undefined" ) {
if ( !Array.isArray(obj[name]) ) {
obj[name] = [ obj[name], item.value ];
} else {
obj[name].Push(item.value);
}
} else {
obj[name] = item.value;
}
return obj;
}, {});
return object;
}
// Function ends
// This is how it's used
$("#getObject").click( function() {
var form_data = $("#form").getFormObject();
console.log(form_data);
});
/* Only to make view better ;) */
#getObject {
padding: 10px;
cursor:pointer;
background:#0098EE;
color:white;
display:inline-block;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<form id="form">
<input type="text" name="text" value="Hola amigo" />
<input type="text" name="text_array[]" value="Array 1" />
<input type="text" name="text_array[]" value="Array 2" />
<input type="text" name="text_array[]" value="Array 3" />
<select name="multiselect" multiple>
<option name="option1" selected> option 1 </option>
<option name="option2" selected> option 2 </option>
</select>
<input type="checkbox" name="checkbox" value="checkbox1" checked/>
<input type="checkbox" name="checkbox" value="checkbox2" checked/>
<input type="radio" name="radio" value="radio1" checked/>
<input type="radio" name="radio" value="radio2"/>
</form>
<div id="getObject"> Get object (check the console!) </div>
function getFormData($form){
var unindexed_array = $form.serializeArray();
var indexed_array = {};
$.map(unindexed_array, function(n, i){
if(indexed_array[n['name']] == undefined){
indexed_array[n['name']] = [n['value']];
}else{
indexed_array[n['name']].Push(n['value']);
}
});
return indexed_array;
}
J'ai écrit une bibliothèque pour résoudre ce problème même: JSONForms . Il prend une forme, passe en revue chaque entrée et construit un objet JSON que vous pouvez facilement lire.
Disons que vous avez le formulaire suivant:
<form enctype='application/json'>
<input name='places[0][city]' value='New York City'>
<input type='number' name='places[0][population]' value='8175133'>
<input name='places[1][city]' value='Los Angeles'>
<input type='number' name='places[1][population]' value='3792621'>
<input name='places[2][city]' value='Chicago'>
<input type='number' name='places[2][population]' value='2695598'>
</form>
Passer le formulaire à la méthode encode de JSONForms vous renvoie l'objet suivant:
{
"places": [
{
"city": "New York City",
"population": 8175133
},
{
"city": "Los Angeles",
"population": 3792621
},
{
"city": "Chicago",
"population": 2695598
}
]
}
Voici démo avec votre formulaire.
affichage des champs d'élément d'entrée du formulaire et du fichier d'entrée pour soumettre votre formulaire sans actualisation de la page et récupérer toutes les valeurs avec le fichier include, le voici
<form id="imageUploadForm" action="" method="post" enctype="multipart/form-data">
<input type="text" class="form-control" id="fname" name='fname' placeholder="First Name" >
<input type="text" class="form-control" name='lname' id="lname" placeholder="Last Name">
<input type="number" name='phoneno' class="form-control" id="phoneno" placeholder="Phone Number">
<textarea class="form-control" name='address' id="address" rows="5" cols="5" placeholder="Your Address"></textarea>
<input type="file" name="file" id="file" >
<input type="submit" id="sub" value="Registration">
</form>
$('#imageUploadForm').on('submit',(function(e)
{
fname = $('#fname').val();
lname = $('#lname').val();
address = $('#address').val();
phoneno = $('#phoneno').val();
file = $('#file').val();
e.preventDefault();
var formData = new FormData(this);
formData.append('file', $('#file')[0]);
formData.append('fname',$('#fname').val());
formData.append('lname',$('#lname').val());
formData.append('phoneno',$('#phoneno').val());
formData.append('address',$('#address').val());
$.ajax({
type:'POST',
url: "test.php",
//url: '<?php echo base_url().'edit_profile/edit_profile2';?>',
data:formData,
cache:false,
contentType: false,
processData: false,
success:function(data)
{
alert('Data with file are submitted !');
}
});
}))
$(form).serializeArray().reduce(function (obj, item) {
if (obj[item.name]) {
if ($.isArray(obj[item.name])) {
obj[item.name].Push(item.value);
} else {
var previousValue = obj[item.name];
obj[item.name] = [previousValue, item.value];
}
} else {
obj[item.name] = item.value;
}
return obj;
}, {});
Cela résoudra le problème: impossible de travailler avec des multi-sélections.
J'ai écrit une fonction qui prend en charge plusieurs cases à cocher et plusieurs sélections. Dans ces cas, il retourne un tableau.
function getFormData(formId) {
return $('#' + formId).serializeArray().reduce(function (obj, item) {
var name = item.name,
value = item.value;
if (obj.hasOwnProperty(name)) {
if (typeof obj[name] == "string") {
obj[name] = [obj[name]];
obj[name].Push(value);
} else {
obj[name].Push(value);
}
} else {
obj[name] = value;
}
return obj;
}, {});
}
Vous n'êtes pas tout à fait correct. Vous ne pouvez pas écrire:
formObj[input.name] = input.value;
Parce que de cette façon, si vous avez une liste multisélectionnée, ses valeurs seront remplacées par la dernière, car elles sont transmises sous la forme: "param1": "valeur1", "param1": "valeur2".
Donc, la bonne approche est:
if (formData[input.name] === undefined) {
formData[input.name] = input.value;
}
else {
var inputFieldArray = $.merge([], $.isArray(formData[input.name]) ? formData[input.name] : [formData[input.name]]);
$.merge(inputFieldArray, [input.value]);
formData[input.name] = $.merge([], inputFieldArray);
}
Cette méthode devrait le faire. Il sérialise les données de formulaire et les convertit ensuite en un objet. S'occupe également des groupes de cases à cocher.
function getFormObj(formId) {
var formParams = {};
$('#' + formId)
.serializeArray()
.forEach(function(item) {
if (formParams[item.name]) {
formParams[item.name] = [formParams[item.name]];
formParams[item.name].Push(item.value)
} else {
formParams[item.name] = item.value
}
});
return formParams;
}
Voici une fonction Nice Vanilla JS que j'ai écrite pour extraire les données de formulaire sous forme d'objet. Il comporte également des options permettant d'insérer des ajouts dans l'objet et d'effacer les champs de saisie de formulaire.
const extractFormData = ({ form, clear, add }) => {
return [].slice.call(form.children).filter(node => node.nodeName === 'INPUT')
.reduce((formData, input) => {
const value = input.value
if (clear) { input.value = '' }
return {
...formData,
[input.name]: value
}
}, add)
}
Voici un exemple d'utilisation avec une demande de publication:
submitGrudge(e) {
e.preventDefault()
const form = e.target
const add = { id: Date.now(), forgiven: false }
const grudge = extractFormData({ form, add, clear: true })
// grudge = {
// "name": "Example name",
// "offense": "Example string",
// "date": "2017-02-16",
// "id": 1487877281983,
// "forgiven": false
// }
fetch('http://localhost:3001/api/grudge', {
method: 'post',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(grudge)
})
.then(response => response.json())
.then(grudges => this.setState({ grudges }))
.catch(err => console.log('error: ', err))
}