jQuery: Loop through elements by class and create associative array - javascript

I have a variable list of elements and need to get their names and values in pairs (associative array or object).
So far I have the following but how do I create the pairs of name and value for each element ?
var names = [];
var values = [];
$('.modalField').each(function() {
fieldName = $(this).attr('name');
fieldVal = $(this).val();
names.push(fieldName);
values.push(fieldVal);
});
Thanks for any help,
Tom

Use bracket notation.
var assoc = {};
$('.modalField').each(function() {
let fieldName = $(this).attr('name');
let fieldVal = $(this).val();
assoc[fieldName] = fieldVal;
});
(Also, you should initialize your variables with let/var/const inside the function so they don't leak into the global scope.)

Something like this?
var fields = [];
$('.modalField').each(function() {
var name = $(this).attr('name');
var value = $(this).val();
fields.push({ name, value });
});
console.log(fields);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div>
<input class="modalField" name="n1" value="v1" />
<input class="modalField" name="n2" value="v2" />
<input class="modalField" name="n3" value="v3" />
</div>
Output:
[
{
"name": "n1",
"value": "v1"
},
{
"name": "n2",
"value": "v2"
},
{
"name": "n3",
"value": "v3"
}
]

Instead of having name & values array, I would suggest you to create an object.
var obj ={};
$('.modalField').each(function() {
obj[$(this).attr('name')] = $(this).val();
});
So this way you will have your object like this (names used as example only): {"name1":"val1","name2":"val2","name3":"val3"}

You say name-value but you seem to want an object
You can do EITHER
// Object
const obj = {};
$('.modalField').each(function() {
const fieldName = $(this).attr('name');
const fieldVal = $(this).val();
obj[fieldName] = fieldVal
});
console.log(obj)
// OR Name-Value pair
const arr = $('.modalField').map(function() {
return {
[$(this).attr('name')]: $(this).val()
}
}).get()
console.log(arr)
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input name="a" value="1" class="modalField" />
<input name="b" value="2" class="modalField" />
<input name="c" value="3" class="modalField" />
<input name="d" value="4" class="modalField" />

Related

Why "for in" inside "for loop" can't change each input value in form element with each object value

Hello Everyone!
I want to make some function() that is useful for changing each input values in selected form ​​dynamically with each Object values, but sadly my example code below it only show "pineapple"
document.getElementById("change-val").addEventListener("click", function(event) {
let dataObj = {
fruit1: "melon",
fruit2: "mango",
fruit3: "pineapple"
};
let FormInput = document.getElementsByTagName("input");
for (let index = 0; index < FormInput.length; index++) {
for (let keyObj in dataObj) {
FormInput[index].value = dataObj[keyObj];
}
}
});
<button id="change-val">Change Value</button>
<form>
<input type="text" value="apple"/>
<input type="text" value="watermelon"/>
<input type="text" value="banana"/>
</form>
You shouldn't use nested loops. Use one loop that gets the corresponding property with the index.
You can use Object.values() to get an array of the property values.
document.getElementById("change-val").addEventListener("click", function(event) {
let dataObj = {
fruit1: "melon",
fruit2: "mango",
fruit3: "pineapple"
};
let FormInput = document.getElementsByTagName("input");
let fruits = Object.values(dataObj);
for (let index = 0; index < FormInput.length; index++) {
FormInput[index].value = fruits[index];
}
});
<button id="change-val">Change Value</button>
<form>
<input type="text" value="apple" />
<input type="text" value="watermelon" />
<input type="text" value="banana" />
</form>

Remove empty object from an array javascript

I'm using bootstrap validator to cloning the input and radio elements.
It is working fine, but i have issue while receiving these values as JavaScript array. Because i always have hidden input and radio elements in the DOM so it send empty object.
How i map my array object to receive values
var kids = $(".form--group").map(function() {
return {
kidName: $(this).find('.thevoornaam').val(),
newDob: $(this).find('.date_of_birth').val(),
}
}).get();
console.log(kids)
I'm receiving values like this..
[{kidName: "Test", newDob:"20"},{kidName: "", newDob:""} ]
Always receive second object with empty string.
How can remove the object from array if values are empty or undefined is..
I hope you guys understand my question.
Thanks in advance.
You can use filter to filter out the empty object like this
var kids = $(".form--group").map(function() {
return {
kidName: $(this).find('.thevoornaam').val(),
newDob: $(this).find('.date_of_birth').val(),
}
}).get();
kids = kids.filter(function (kid) {
return kid.kidName && kid.newDob;
});
console.log(kids)
If you want to exclude the item when every property is empty, undefined or 0;
let obj = [{kidName: "Test", newDob:"20"},{kidName: "", newDob:""} ];
let filtered = obj.filter(e=>{
for(let p in e){
if(e[p]){
return true;
}
}
});
console.log(filtered);
Check the strings before you create the objects:
$(document).ready(function(){
var kids = $(".form--group").map(function() {
var kidName = $(this).find('.thevoornaam').val();
var dob = $(this).find('.date_of_birth').val();
var result_arr = [];
if(kidName || dob)
{
var obj = {kidName: kidName, newDob: dob}
result_arr.push(obj);
}
return result_arr;
}).get();
console.log(kids)
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="form--group">
<input class="thevoornaam" value="Test Name" />
<input class="date_of_birth" value="Test Date" />
</div>
<div class="form--group">
<input class="thevoornaam" value="" />
<input class="date_of_birth" value="" />
</div>
<div class="form--group">
<input class="thevoornaam" value="Test Name" />
<input class="date_of_birth" value="Test Date" />
</div>

Jquery add duplicate array key

I need to create a javascript (jquery) array with duplicated key name like next one
{
"apple": "type1",
"apple": "type2",
}
Here is my current code I stack with
var data = {};
jQuery.each(formData, function(i, field) {
data[field.name] = field.value;
});
In above example field.name is "apple" have different values like "type1" or "type2".
With my current code when same field.name in jQuery.each I got removed/erased "apple":"type1"
This is not a jQuery problem, but rather it is to do with the nature of objects in javascript. You can't store multiple values on the same key (how would you access them?).
What you can do is store an array on a key, and add to that:
const formData = jQuery('input');
let data = {};
jQuery('button').click(function() {
data = {}
jQuery.each(formData, function(i, field) {
data[field.name] = data.hasOwnProperty(field.name)
? [...data[field.name], field.value]
: [field.value]
});
console.dir(data);
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input name="a" />
<input name="b" />
<input name="b" />
<button>Test</button>
What the above code does is use an array against a key, and add to that array for each item.
You can do this without jQuery, and without an each, you may or may not prefer this option:
const button = document.querySelector('button');
const getAll = selector => Array.prototype.slice.call(
document.querySelectorAll(selector)
);
let data = {};
button.onclick = () => {
data = getAll('input')
.reduce((result, element) => ({
...result,
[element.name]: result.hasOwnProperty(element.name)
? [...result[element.name], element.value]
: [element.value]
}), {})
console.dir(data)
}
<input name="a" />
<input name="b" />
<input name="b" />
<button>Test</button>

access arbitrary property from object

I have a set of nesting json object like this:
var obj = {
name: "student",
contact: {
phone: "22222",
fax: "33333",
...
},
...
}
And I have these text fields:
<input type="text" name="name" />
<input type="text" name="contact_phone" />
<input type="text" name="contact_fax" />
...
Now I want to fill these fields with appropriate property from above object. My question is how can I access anonymous property from that object?
For example suppose I have this jquery code:
$("#formID").find("input").each(function(index) {
fieldName = $(this).attr("name");
var namePart = fieldName.split("_");
//I want something like this: console.log(obj.namePart[0].namePart[1])
});
Use obj["propertyName"]
obj[namePart[0]][namePart[1]]
$('#formID').find("input").each(function(index) {
fieldName = $(this).attr("name");
var namePart;
if(fieldName.indexOf('_') > -1){
namePart = fieldName.split("_");
console.log(obj[namePart[0]][namePart[1]])
}
else{
namePart = fieldName;
console.log(obj[namePart])
}
});
*Note: The property is not anonymous. If your run obj["propertyName"] on an object with no such property it will return undefined.
<form ID="formID">
<input type="text" name="name" />
<input type="text" name="contact_phone" />
<input type="text" name="contact_fax" />
</form>
$("#formID").find("input").each(function() {
fieldName = $(this).attr("name");
namePart = fieldName.split("_");
if(namePart.length ==1 && namePart[0]=="name"){
$(this).val(obj.name);
}
else if(namePart.length>1){
$(this).val(obj[namePart[0]][namePart[1]]);
}
//I want something like this: console.log(obj.namePart[0].namePart[1])
});
http://jsfiddle.net/57vL6b0w/
Edit: Sorry about that I misunderstood the question. What you are looking for is something like this.
var obj = {
name: "student",
contact: {
phone: "22222",
fax: "33333"
}
};
$('#formID').("input").each(function(index) {
fieldName = $(this).attr("name");
var namePart = fieldName.split("_");
var arbitraryVal = obj;
for (var part in namePart) {
if (arbitraryVal.hasOwnProperty(namePart[part])) {
arbitraryVal = arbitraryVal[namePart[part]];
continue;
}
arbitraryVal = null;
break;
}
if (typeof $(this).val(arbitraryVal) !== 'undefined') {
$(this).val(arbitraryVal);
}
});
recusivly searches an object for each name part. If the name part is
contact_phone It will look for obj.contact.phone if it is something_else_with_lots_of_underscores it will look for obj.something.else.with.lots.of.underscores
JS FIDDLE

How can I get form data with JavaScript/jQuery?

Is there a simple, one-line way to get the data of a form as it would be if it was to be submitted in the classic HTML-only way?
For example:
<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>
Output:
{
"foo": "1",
"bar": "xxx",
"this": "hi"
}
Something like this is too simple, since it does not (correctly) include textareas, selects, radio buttons and checkboxes:
$("#form input").each(function () {
data[theFieldName] = theFieldValue;
});
Use $('form').serializeArray(), which returns an array:
[
{"name":"foo","value":"1"},
{"name":"bar","value":"xxx"},
{"name":"this","value":"hi"}
]
Other option is $('form').serialize(), which returns a string:
"foo=1&bar=xxx&this=hi"
Take a look at this jsfiddle demo
$('form').serialize() //this produces: "foo=1&bar=xxx&this=hi"
demo
Updated answer for 2014: HTML5 FormData does this
var formData = new FormData(document.querySelector('form'))
You can then post formData exactly as it is - it contains all names and values used in the form.
Based on jQuery.serializeArray, returns key-value pairs.
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
});
This is a nitpicky answer, but let me explain why this is a better solution:
We're properly handling a form submit rather than a button press. Some people like to push enter on fields. Some people use alternative input devices such as speech input or other accessibility devices. Handle the form submit and you correctly solve it for everyone.
We're digging into the form data for the actual form that was submitted. If you change your form selector later, you don't have to change the selectors for all the fields. Furthermore, you might have several forms with the same input names. No need to disambiguate with excessive IDs and what not, just track the inputs based on the form that was submitted. This also enables you to use a single event handler for multiple forms if that is appropriate for your situation.
The FormData interface is fairly new, but is well supported by browsers. It's a great way to build that data collection to get the real values of what's in the form. Without it, you're going to have to loop through all the elements (such as with form.elements) and figure out what's checked, what isn't, what the values are, etc. Totally possible if you need old browser support, but the FormData interface is simpler.
I'm using ES6 here... not a requirement by any means, so change it back to be ES5 compatible if you need old browser support.
It is 2019 and there's a better way to do this:
const form = document.querySelector('form');
const data = new URLSearchParams(new FormData(form).entries());
or if you want a plain Object instead
const form = document.querySelector('form');
const data = Object.fromEntries(new FormData(form).entries());
although note that this won't work with duplicate keys like you get from multi-select and duplicate checkboxes with the same name.
Simplest way, 2022.
document.querySelector('form').addEventListener('submit', (e) => {
const data = Object.fromEntries(new FormData(e.target).entries());
console.log(data)
});
Output
{ name: 'Stackoverflow' }
use .serializeArray() to get the data in array format and then convert it into an object:
function getFormObj(formId) {
var formObj = {};
var inputs = $('#'+formId).serializeArray();
$.each(inputs, function (i, input) {
formObj[input.name] = input.value;
});
return formObj;
}
Here's a really simple and short soluton that even doesn't require 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;
I use this:
jQuery Plugin
(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);
HTML Form
<form id='myform'>
<input name='myVar1' />
<input name='myVar2' />
</form>
Get the Data
var myData = $("#myForm").getFormData();
$("#form input, #form select, #form textarea").each(function() {
data[theFieldName] = theFieldValue;
});
other than that, you might want to look at serialize();
Here is a working JavaScript only implementation which correctly handles checkboxes, radio buttons, and sliders (probably other input types as well, but I've only tested these).
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;
}
Working example:
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>
edit:
If you're looking for a more complete implementation, then take a look at this section of the project I made this for. I'll update this question eventually with the complete solution I came up with, but maybe this will be helpful to someone.
I have included the answer to also give back the object required.
function getFormData(form) {
var rawJson = form.serializeArray();
var model = {};
$.map(rawJson, function (n, i) {
model[n['name']] = n['value'];
});
return model;
}
Based on neuront's response I created a simple JQuery method that gets the form data in key-value pairs but it works for multi-selects and for array inputs with name='example[]'.
This is how it is used:
var form_data = $("#form").getFormObject();
You can find an example below of its definition and how it works.
// 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>
If you are using jQuery, here is a little function that will do what you are looking for.
First, add an ID to your form (unless it is the only form on the page, then you can just use 'form' as the dom query)
<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>
The output would look like:
{
"foo": "1",
"bar": "xxx",
"this": "hi"
}
You can also use the FormData Objects; The FormData object lets you compile a set of key/value pairs to send using XMLHttpRequest. Its primarily intended for use in sending form data, but can be used independently from forms in order to transmit keyed data.
var formElement = document.getElementById("myform_id");
var formData = new FormData(formElement);
console.log(formData);
This will append all form fields to the JavaScript object "res":
var res = {};
$("#form input, #form select, #form textarea").each(function(i, obj) {
res[obj.name] = $(obj).val();
})
var formData = new FormData($('#form-id'));
params = $('#form-id').serializeArray();
$.each(params, function(i, val) {
formData.append(val.name, val.value);
});
For those of you who would prefer an Object as opposed to a serialized string (like the one returned by $(form).serialize(), and a slight improvement on $(form).serializeArray()), feel free to use the code below:
var Form = {
_form: null,
_validate: function(){
if(!this._form || this._form.tagName.toLowerCase() !== "form") return false;
if(!this._form.elements.length) return false;
return true;
}, _loopFields: function(callback){
var elements = this._form.elements;
for(var i = 0; i < elements.length; i++){
var element = form.elements[i];
if(name !== ""){
callback(this._valueOfField(element));
}
}
}, _valueOfField: function(element){
var type = element.type;
var name = element.name.trim();
var nodeName = element.nodeName.toLowerCase();
switch(nodeName){
case "input":
if(type === "radio" || type === "checkbox"){
if(element.checked){
return element.value;
}
}
return element.value;
break;
case "select":
if(type === "select-multiple"){
for(var i = 0; i < element.options.length; i++){
if(options[i].selected){
return element.value;
}
}
}
return element.value;
break;
case "button":
switch(type){
case "reset":
case "submit":
case "button":
return element.value;
break;
}
break;
}
}, serialize: function(form){
var data = {};
this._form = form;
if(this._validate()){
this._loopFields(function(value){
if(value !== null) data[name] = value;
});
}
return data;
}
};
To execute it, just use Form.serialize(form) and the function will return an Object similar to this:
<!-- { username: "username", password: "password" } !-->
<input type="text" value="username">
<input type="password" value="password">
As a bonus, it means you don't have to install the entire bundle of jQuery just for one serialize function.
I'm kind of supprised because no one mentioned below solution.
Get form data via document.forms.namedItem function
var form = document.forms.namedItem("fileinfo");
form.addEventListener('submit', function(ev) {
var oData = new FormData(form);
}
The HT
<form name="fileinfo">
<label>Your email address:</label>
<input type="email" autocomplete="on" autofocus name="userid" placeholder="email" required size="32" maxlength="64" /><br />
<label>Custom file label:</label>
<input type="text" name="filelabel" size="12" maxlength="32" /><br />
<label>File to stash:</label>
<input type="file" name="file" required />
<input type="submit" value="Stash the file!" />
</form>
<div></div>
I wrote a library to solve this very problem: JSONForms. It takes a form, goes through each input and builds a JSON object you can easily read.
Say you have the following form:
<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>
Passing the form to JSONForms' encode method returns you the following object:
{
"places": [
{
"city": "New York City",
"population": 8175133
},
{
"city": "Los Angeles",
"population": 3792621
},
{
"city": "Chicago",
"population": 2695598
}
]
}
Here's demo with your form.
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;
}
you can use this function for have an object or a JSON from form.
for use it:
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;
}
$( "form" ).bind( "submit", function(e) {
e.preventDefault();
console.log( $(this).serializeObject() );
//console.log( $(this).serialize() );
//console.log( $(this).serializeArray() );
});
$.fn.serializeObject = function() {
var o = {};
var a = this.serializeArray();
$.each( a, function() {
if ( o[this.name] !== undefined)
{
if ( ! o[this.name].push )
{
o[this.name] = [o[this.name]];
}
o[this.name].push(this.value || '');
}
else
{
o[this.name] = this.value || '';
}
});
return o;
};
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<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>
</select>
<input type="submit" value="Submit" />
</form>
Codepen
I wrote a function that takes care of multiple checkboxes and multiple selects. In those cases it returns an array.
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;
}, {});
}
Here is a nice vanilla JS function I wrote to extract form data as an object. It also has options for inserting additions into the object, and for clearing the form input fields.
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)
}
Here is an example of its use with a post request:
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))
}
showing form input element fields and input file to submit your form without page refresh and grab all values with file include in it here it is
<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>
on Submit button page will send ajax request to your php file.
$('#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;
}, {});
It will fix issue:couldn't work with multiselects.
Here's my version in vanilla JS (tested on Chrome)
works with:
name="input"
name="form[name]" (creates an object)
name="checkbox[]" (creates an object with an array)
name="form[checkbox][]" (creates an array)
name="form[select][name]" (creates an object with an object containing only the selected value)
/**
* Get the values from a form
* #param formId ( ID without the # )
* #returns {object}
*/
function getFormValues( formId )
{
let postData = {};
let form = document.forms[formId];
let formData = new FormData( form );
for ( const value of formData.entries() )
{
let container = postData;
let key = value[0];
let arrayKeys = key.match( /\[[\w\-]*\]/g ); // Check for any arrays
if ( arrayKeys !== null )
{
arrayKeys.unshift( key.substr( 0, key.search( /\[/ ) ) ); // prepend the first key to the list
for ( let i = 0, count = arrayKeys.length, lastRun = count - 1; i < count; i++ )
{
let _key = arrayKeys[i];
_key = _key.replace( "[", '' ).replace( "]", '' ); // Remove the brackets []
if ( _key === '' )
{
if ( ! Array.isArray( container ) )
{
container = [];
}
_key = container.length;
}
if ( ! (_key in container) ) // Create an object for the key if it doesn't exist
{
if ( i !== lastRun && arrayKeys[i + 1] === '[]' )
{
container[_key] = [];
}
else
{
container[_key] = {};
}
}
if ( i !== lastRun ) // Until we're the last item, swap container with it's child
{
container = container[_key];
}
key = _key;
}
}
container[key] = value[1]; // finally assign the value
}
return postData;
}
You are all not fully correct. You cannot write:
formObj[input.name] = input.value;
Because this way if you have multiselect list - its values will be overwritten with the last one, since it's transmitted as: "param1" : "value1", "param1" : "value2".
So, correct approach is:
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);
}

Categories