Is there any better solution to convert a form data that is already serialized by jQuery function serialize(), when the form contains multiple input Array fields. I want to be able to convert the form data in to a JSON object to recreate some other informative tables. So tell me a better way to get the serialize string converted as a JSON object.
<form id='sampleform'>
<input name='MyName' type='text' /> // Raf
<!--array input fields below-->
<input name='friendname[]' type='text' /> // Bily
<input name='fiendemail[]' type='text' /> // bily#someemail.com
<!--duplicated fields below to add more friends -->
<input name='friendname[]' type='text' /> // Andy
<input name='fiendemail[]' type='text' /> // Andy#somwhere.com
<input name='friendname[]' type='text' /> // Adam
<input name='fiendemail[]' type='text' /> // Adam#herenthere.com
</form>
The jquery method applied to get the data
var MyForm = $("#sampleform").serialize();
/** result : MyName=Raf&friendname[]=Billy&fiendemail[]=bily#someemail.com&friendname[]=Andy&fiendemail[]=Andy#somwhere.com&friendname[]=Adam&fiendemail[]=Adam#herenthere.com
*/
how do I make this data in to a JSON object?
which should have the following example JSON data from the above form.
{
"MyName":"raf",
"friendname":[
{"0":"Bily"},
{"1":"Andy"},
{"2":"Adam"}
],
"friendemail":[
{"0":"bily#someemail.com"},
{"1":"Andy#somwhere.com"},
{"2":"Adam#herenthere.com"}
]
}
var formdata = $("#myform").serializeArray();
var data = {};
$(formdata ).each(function(index, obj){
data[obj.name] = obj.value;
});
Simple and fast ;)
I have recently had this exact problem. Initially, we were using jQuery's serializeArray() method, but that does not include form elements that are disabled. We will often disable form elements that are "sync'd" to other sources on the page, but we still need to include the data in our serialized object. So serializeArray() is out. We used the :input selector to get all input elements (both enabled and disabled) in a given container, and then $.map() to create our object.
var inputs = $("#container :input");
var obj = $.map(inputs, function(n, i)
{
var o = {};
o[n.name] = $(n).val();
return o;
});
console.log(obj);
Note that for this to work, each of your inputs will need a name attribute, which will be the name of the property of the resulting object.
That is actually slightly modified from what we used. We needed to create an object that was structured as a .NET IDictionary, so we used this: (I provide it here in case it's useful)
var obj = $.map(inputs, function(n, i)
{
return { Key: n.name, Value: $(n).val() };
});
console.log(obj);
I like both of these solutions, because they are simple uses of the $.map() function, and you have complete control over your selector (so, which elements you end up including in your resulting object). Also, no extra plugin required. Plain old jQuery.
Use the jQuery.serializeJSON plugin.
It converts forms using the same format as what you would find in a Rails params object, which is very standard and well tested.
I'm using this very little jQuery plugin, that I've extended from DocumentCloud:
https://github.com/documentcloud/documentcloud/blob/master/public/javascripts/lib/jquery_extensions.js
It is basically two lines of code, but it requires _.js (Underscore.js), since it is based on a reduce function.
$.fn.extend({
serializeJSON: function(exclude) {
exclude || (exclude = []);
return _.reduce(this.serializeArray(), function(hash, pair) {
pair.value && !(pair.name in exclude) && (hash[pair.name] = pair.value);
return hash;
}, {});
}
});
Extensions:
It doesn't serialize an input value if it's null
It can exclude some inputs by passing an array of input names to the exclude argument i.e. ["password_confirm"]
I think there're a lot of good answer here, and I made my own function based on these answers.
function formToJSON(f) {
var fd = $(f).serializeArray();
var d = {};
$(fd).each(function() {
if (d[this.name] !== undefined){
if (!Array.isArray(d[this.name])) {
d[this.name] = [d[this.name]];
}
d[this.name].push(this.value);
}else{
d[this.name] = this.value;
}
});
return d;
}
//The way to use it :
$('#myForm').submit(function(){
var datas = formToJSON(this);
return false;
});
Well let me explain basically why I prefer this solution...
If you have multiples input with the same name, all values will be stored in an Array but if not, the value will be stored directly as the value of the index in the JSON ... This is where it's different from Danilo Colasso's answer where the JSON returned is only based of array values...
So if you have a Form with a textarea named content and multiples authors, this function will return to you :
{
content : 'This is The Content',
authors :
[
0: 'me',
1: 'you',
2: 'him',
]
}
An equivalent solution to Danilo Colasso's, with the sames pros and cons of .serializeArray() (basically it uses .reduce instead of $.each).
With little effort it allows implementing the extra features in S.C.'s answers without requiring extensions.
$(selector).serializeArray()
.reduce(function(accum, item) {
// This 'if' allows ignoring some values
if (-1 === [ 'ignoreThis', 'andThat' ].indexOf(item.name)) {
// This allows ignoring NULL values
if (item.value !== null) {
accum[item.name] = item.value;
}
}
return accum;
},
{
// By supplying some initial values, we can add defaults
// for, say, disabled form controls.
preFilledName: preFilledValue, // optional
defaultName : defaultValue // optional
}
);
if you can use ES6, you could do
const obj = arr.reduce((acc, {name, value}) => ({...acc, [name]: value}), {})
for a serialized array works very well.
var formdata = $("#myform").serializeArray();
var data = {};
$(formdata ).each(function(index, obj){
if(data[obj.name] === undefined)
data[obj.name] = [];
data[obj.name].push(obj.value);
});
Using underscore & jQuery
var formdata = $("#myform").serializeArray();
var data = {};
_.each(formdata, function(element){
// Return all of the values of the object's properties.
var value = _.values(element);
// name : value
data[value[0]] = value[1];
});
console.log(data); //Example => {name:"alex",lastname:"amador"}
Using the power of reducing function!
$(form).serializeArray().reduce(function (output, value) {
output[value.name] = value.value
return output
}, {})
With all Given Answer there some problem which is...
If input name as array like name[key], but it will generate like this
name:{
key : value
}
For Example :
If i have form like this.
<form>
<input name="name" value="value" >
<input name="name1[key1]" value="value1" >
<input name="name2[key2]" value="value2" >
<input name="name3[key3]" value="value3" >
</form>
Then It will Generate Object like this with all given Answer.
Object {
name : 'value',
name1[key1] : 'value1',
name2[key2] : 'value2',
name3[key3] : 'value3',
}
But it have to Generate like below,anyone want to get like this as below.
Object {
name : 'value',
name1 : {
key1 : 'value1'
},
name2 : {
key2 : 'value2'
},
name3 : {
key2 : 'value2'
}
}
Then Try this below js code.
(function($) {
$.fn.getForm2obj = function() {
var _ = {};
$.map(this.serializeArray(), function(n) {
const keys = n.name.match(/[a-zA-Z0-9_]+|(?=\[\])/g);
if (keys.length > 1) {
let tmp = _;
pop = keys.pop();
for (let i = 0; i < keys.length, j = keys[i]; i++) {
tmp[j] = (!tmp[j] ? (pop == '') ? [] : {} : tmp[j]), tmp = tmp[j];
}
if (pop == '') tmp = (!Array.isArray(tmp) ? [] : tmp), tmp.push(n.value);
else tmp[pop] = n.value;
} else _[keys.pop()] = n.value;
});
return _;
}
console.log($('form').getForm2obj());
$('form input').change(function() {
console.clear();
console.log($('form').getForm2obj());
});
})(jQuery);
console.log($('form').getForm2obj());
<script src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
<form>
<input name="name" value="value">
<input name="name1[key1]" value="value1">
<input name="name2[key2]" value="value2">
<input name="name3[key3]" value="value3">
<input type="checkbox" name="name4[]" value="1" checked="checked">
<input type="checkbox" name="name4[]" value="2">
<input type="checkbox" name="name4[]" value="3">
</form>
if you are using ajax requests then no need to make it json-object only $('#sampleform').serialize() works excellently or if you have another purpose here is my solution:
var formserializeArray = $("#sampleform").serializeArray();
var jsonObj = {};
jQuery.map(formserializeArray , function (n, i) {
jsonObj[n.name] = n.value;
});
Use JSON.stringify() and serializeArray():
console.log(JSON.stringify($('#sampleform').serializeArray()));
Related
what is the easiest way to retrieve form values to send to localStorage as a JSON string? I started a function with a for loop but am stuck..any nudges are greatly appreciated(still very new to this) No JQuery please. Thank you
<input type="submit" name="submit" value="submitOrder" onclick="return getValues();">
var userOrder='';
function getValues(){
for(var i=0; i < document.forms[0].length - 1; i++){
console.log(document.forms[0][i]);
return false;
}
}
localStorage.setItem('userOrder',JSON.stringify(userOrder));
console.log(localStorage.getItem('userOrder'));
You could do it like this:
html:
<form id="myform">
<input type="text" name="test">
<input type="submit" value="submitOrder">
</form>
js:
const userOrder = {};
function getValues(e) {
// turn form elements object into an array
const elements = Array.prototype.slice.call(e.target.elements);
// go over the array storing input name & value pairs
elements.forEach((el) => {
if (el.type !== "submit") {
userOrder[el.name] = el.value;
}
});
// finally save to localStorage
localStorage.setItem('userOrder', JSON.stringify(userOrder));
}
document.getElementById("myform").addEventListener("submit", getValues);
No need for jQuery. This uses ES 2015 syntax but if you need to support old browsers just run it through babel.
// Iterate over all the forms in the document as an array,
// the [...stuff] turns the nodelist into a real array
let userdata = [...document.forms].map(form => {
// iterate over all the relevant elements in the form and
// create key/value pairs for the name/object
return [...form.elements].reduce((obj, el) => {
// Every form control should have a name attribute
obj[el.name] = el.value;
return obj;
}, {});
});
// convert the data object to a JSON string and store it
localStorage.setItem('userOrder', JSON.stringify(userdata));
// pull it pack out and parse it back into an object
let data = JSON.parse(localStorage.getItem('userOrder'));
If the forms all have ids (and they should) you could also use reduce in the outer layer instead of map and hash on the form id:
let userdata = [...document.forms].reduce((result, frm) => {
result[frm.id] = [...frm.elements].reduce((obj, el) => {
and so on.
In ExpressJS using body-parser, there exists the functionality to parse as a JavaScript object (or JSON, I'm not entirely sure) a set of input elements which have the same name attribute with defined keys.
HTML (e.g.):
<input type="text" class="name" name="name[foo]" placeholder="input1"/>
<input type="text" class="name" name="name[bar]" placeholder="input2"/>
JavaScript (e.g.):
var obj = req.body.name;
The object obj is understood by JavaScript to be { "foo" : input1, "bar" : input2 }
I am trying to get similar functionality using standard jQuery to handle several related form inputs. What I have tried so far—to no avail—is the following:
$(".name") yields an Object containing the literal HTML (not helpful for grabbing the key-value pairs).
$(".name").map(function () {return $(this).val();}).get(); yields an array of values, but no keys.
$("input[name='name']") and $("input[name='name[]']") yield nothing.
I have also tried the following to convert the inputs to an array, but it still does not serve the purpose of pulling the information from the form as a JavaScript object/JSON:
$.fn.inputsToArray = function () {
var values= [];
$.each(this, function (i, field) {
values.push(field.value);
});
return values;
};
Is there a way to accomplish what I am trying to do without NodeJS / body-parser?
Solution:
Thanks to gaetanoM's excellent solution (accepted below), I was able to create a generic jQuery function that can be called on any jQuery object (obviously, it'll only work properly if the element is in the <input ... name="example[key]" ... /> format, but I digress).
The function is called thusly:
var output = $(":input[name^=example]").inputsToObject();
The function is defined as the following:
$.fn.inputsToObject = function () {
var values = {};
values = $(this).get().reduce(function (acc, ele) {
var key = ele.name.match(/\[(.*)\]$/)[1];
acc[key] = $(ele).val();
return acc;
}, {})
return values;
}
For the first you need $(':input[name^=name]') in order to select all input fields having the name attribute starting with name. With .get() you transform the jQuery result into an array on which you can apply .reduce():
var result = $(':input[name^=name]').get().reduce(function(acc, ele) {
var key = ele.name.match(/\[(.*)\]$/)[1]; // get the key
acc[key] = ele.getAttribute('placeholder'); // add to retval
return acc;
}, {});
console.log(result);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="text" class="name" name="name[foo]" placeholder="input1"/>
<input type="text" class="name" name="name[bar]" placeholder="input2"/>
I have a set of checkboxes and want to concatenate only the checked ones into a query string, but for some reason val() only returns the first one. The jQuery API docs mention that selects can return an array form the .val() function, can I get this same behavior for inputs as well, with a prototype or jquery plugin?
Here's my code:
$('.boxes input:checked');
// [ <input type="checkbox" value="val1">, <input type="checkbox" value="val2">, <input type="checkbox" value="val3"> ]
$('.boxes input:checked').val();
// "val1"
Ideally the second console output would be:
$('.boxes input:checked').val();
// [ "val1", "val2", "val3" ]
val returns an array of selected values for select elements that have multiple attribute, for other elements it returns the value of the first element in the set. You can use the map method:
var values = $('.boxes input:checked').map(function() {
return this.value;
}).get();
You can also define a method:
$.fn.vals = function() {
var first = this.get(0);
if ( this.length === 0 ) return [];
if ( first.tagName === 'SELECT' && first.multiple ) {
return this.val();
}
return this.map(function() { return this.value; }).get();
}
// ...
var values = $('.boxes input:checked').vals();
I have a form with inputs that look like this:
<form id="myForm">
<input type="text" name="location[0]">
<input type="text" name="location[1]">
<input type="text" name="user[0]">
<input type="text" name="user[1]">
...
</form>
I am making an ajax call with the form data as the post body. When I try to serialize the form ($("#myForm").serializeArray), I do not get arrays within an array. I still get all fields as their own separate objects like so:
[
{
name: "location[0]",
value: "123"
},
{
name: "location[1]",
value: "456"
}
...
]
How do I serialize the form so that I have a multidimensional array as the data to send to my backend (in Scala)? I want it to look like:
[
{ name: "location",
value: [123, 456]
},
{ name: "user",
value: ["Jim", "Jane"]
}
]
Fiddle https://jsfiddle.net/w8bu4s10/
I don't know a basic function but you can use this function:
function getArray(element){
var result = new Array();
$(element).find('input').each(function(i,e){
// extract path from name
var path = $(e).attr('name').split('[');
for(var key in path){
if(path[key].endsWith(']')){
path[key] = path[key].substr(0, path[key].length-1);
}
}
// create path inside result array
var node = result;
for(var depth in path){
if(depth == path.length-1){
if(Number.isInteger(path[depth])){
node.splice(path[depth], 0, $(e).val());
}else{
node.push($(e).val());
}
}else{
var found = false;
for(var key in node){
if(node[key].name == path[depth]){
found = true;
node = node[key].value;
break;
}
}
if(!found){
var obj = new Object();
obj['name'] = path[depth];
obj['value'] = new Array();
node.push(obj);
node = node[node.length - 1].value;
}
}
}
});
return JSON.stringify(result);
}
I figured out how to do it. Name all inputs with array brackets at the end, but do not specify an index in []. Even though it doesn't look like a proper array value when printing the result of form.serializeArray(), the backend will properly interpret it. In my case, Scala Play consolidated all values with the same key into an ArrayBuffer.
What is a simple way to construct
{
type: [ "company", "product", "service" ]
}
out of:
<input type="radio" name="type" value="company">Company
<input type="radio" name="type" value="product">Product
<input type="radio" name="type" value="service">Service
Using any library such as jQuery or Underscore.js, or plain JavaScript?
A little explanation, since it seems to be confusing:
Construct the object dynamically. That means that these HTML elements will produce the object shown, but if the name attribute was "profile", and the values were different, the result would be:
{
profile: [ "profile1", "profile2", "profile3" ]
}
This should do it fairly easily using jquery:
function getInputValues(name)
{
return $('input[name="' + name + '"]').map(function() {
return this.value;
}).get();
}
var data = {
type: getInputValues('type')
};
With native JavaScript:
function getInputValues(name)
{
return [].map.call(document.getElementsByName(name), function(item) {
return item.value;
});
}
Though, this assumes that the name you pass is always an <input> element; if that's a concern you should use a query selector instead.
Demo
Here's a non-jQuery solution
var inputs = querySelectorAll("input[name=type]");
var obj = {};
obj.type = [].map.call(inputs, function(elem) {
return elem.value;
});