HTML form for multiple objects when converting to JSON - javascript

Edited:
$.fn.serializeObject = function() {
var o = {};
var a = this.serializeArray();
$.each(a, function() {
var value = this.value || '';
if (/^\d+$/.test(value))
value = +value;
if (o[this.name] !== undefined) {
if (!o[this.name].push) {
o[this.name] = [o[this.name]];
}
o[this.name].push(value);
} else {
o[this.name] = value;
}
});
return o;
};`
Edited to hopefully make clearer.
Having difficulty wrapping my head around this - sleep deprivation = madness.
I have a form that simply serialises the data into JSON and stores it for later use.
<form id="form" method="post">
a? <input class="number" type="text" name="a" size="5" maxlength="5"/><br/>
Item 1:
Type?:<br/>
<select size="2" name="type">
<option value="1">b</option>
<option value="2">c</option>
</select>
d:<input class="number" type="text" name="d" maxlength="2" size="2"/> <br/>
e:<input class="number" type="text" name="e" maxlength="2" size="2"/> <br/>
<p>Item 2:</p>
Type?:<br/>
<select size="2" name="type">
<option value="1">b</option>
<option value="2">c</option>
</select>
d:<input class="number" type="text" name="d" maxlength="2" size="2"/> <br/>
e:<input class="number" type="text" name="e" maxlength="2" size="2"/> <br/>
<input type="submit" />
when the form is serialised the result I get is:
JSON{
"a":1,
"type":[1,2],
"d":[99,33],
"e":[99,33]
}
what I need is the typical tree structure of JSON something where each item has its own level, something like:
{
"a": "1",
"item1":
{
"type": "1",
"d": "99",
"e": "99",
},
"item2":
{
"type": "2",
"d": "33",
"e": "33",
}
Ideally I'd like to have an option whereby the user can state how many items the form should request information for but I need a basic working example first.
once I have this data I'm then converting it into JSON and would like a tree like structure if possible. Any help appreciated. This post How to serialize a form into an object (with tree structure)? helps a lot but its the structure of the HTML I'm having issues with. Thanks again.

A quick and dirty way would be this: change the name of your inputs based on their item number:
<input name="item1.a" ... />
<input name="item2.a" ... />
<input name="item3.a" ... />
Then modify the serializeObject() to look for the dots:
...
$.each(a, function() {
var value = this.value || '';
if (/^\d+$/.test(value))
value = +value;
if ( this.name && this.name.indexOf('.') )
{
var split = this.name.split('.');
o[ split[0] ] = o[ split[0] ] || {};
o[ split[0] ][ split[1] ] = value
}
else if (o[this.name] !== undefined) {
if (!o[this.name].push) {
o[this.name] = [o[this.name]];
}
o[this.name].push(value);
} else {
o[this.name] = value;
}
});
...
NOTE: This code isn't perfect, but it will get you in the right direction!

I'd introduce new html attribute:
<input data-item="1" class="number" type="text" name="d" maxlength="2" size="2"/>
<select data-item="1" size="2" name="type"> ...
and then I'd use
$(this).attr('data-item');
to read value and place it in right object. Other option is to get elements only for specified item (in some loop):
$('input[data-item="1"], select[data-item="1"]').each(...);
EDIT
I see no pretty way of using serializeArray() to achieve this, but I'd go for item number in name attribute (name="type1") or again for loop with i as item number:
$('[data-item="'+i+'"]', this).serializeArray();

Related

How to receive value as each separate object javascript

I'm trying to receive value as separate object array for each element.
This is my code
<input class="name" name="name[]" type="text" />
<input class="date_of_birth" name="DoB[]" type="text" />
<input class="age" type="radio" name="age" value="1" />
<input class="age" type="radio" name="age" value="0" />
var kidName = [];
$(".name").each(function() {
kidName.push($(this).val());
});
var newDob = [];
$(".date_of_birth").each(function() {
newDob.push($(this).val());
});
var age = [];
$(".age:checked").each(function() {
age.push($(this).val());
});
var kids = {
"kidName": kidName,
"newDob": newDob,
"age": age
};
How i get the value with this as separate array for each element.
kids: {
kidName: ["Test1", "Test2"]
newDob: ["20/02/2000", "20/03/2018"]
age: ["19", "1"]
}
But i want to receive these values like this
kids:
{
kidName: ["Test1"],
newDob: ["20/02/2000"],
age: ["19"]
},
{
kidName: ["Test2"],
newDob: ["20/03/2018"],
age: ["1"]
}
How can i achieve this, what changes should i make to receive values like this?
Thanks
One option is to put the form group into a container. Select the container and use map to loop thru the containers. In this example, the container is a div with class input-group
Note: you need to change the name of radio button every container.
var result = $(".input-group").map(function() {
return {
kidName: $(this).find('.name').val(),
newDob: $(this).find('.date_of_birth').val(),
age: $(this).find('.age:checked').val(),
}
}).get();
console.log(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="input-group">
<input class="name" name="name[]" type="text" value="Test1" />
<input class="date_of_birth" name="DoB[]" type="text" value="20/02/2000" />
<input class="age" type="radio" name="age01[]" value="1" checked/>
<input class="age" type="radio" name="age01[]" value="0" />
</div>
<div class="input-group">
<input class="name" name="name[]" type="text" value="Test2" />
<input class="date_of_birth" name="DoB[]" type="text" value="20/03/2018" />
<input class="age" type="radio" name="age02[]" value="1" />
<input class="age" type="radio" name="age02[]" value="0" checked/>
</div>
Based on what is present in your question, the best I can suggest is just to reformat the data you have into the format you need.
Id you're able to provide your html, it may be possible to get the data into this format initially rather than reparsing it.
const kids = {
kidName: ["Test1", "Test2"],
newDob: ["20/02/2000", "20/03/2018"],
age: ["19", "1"],
};
const kidsArraysToObjects = kids => kids.kidName.map(
(_, i) => Object.keys(kids).reduce((prev, curr) => ({
...prev,
[curr]: kids[curr][i]
}), {})
)
const result = kidsArraysToObjects(kids)
console.dir(result)
Here is what i have tried
var kids = []
$(".name").each(function(index, value) {
if (kids[index] == undefined) {
kids[index] = {}
}
kids[index].kidName = $(this).val()
});
$(".date_of_birth").each(function(index, value) {
if (kids[index] == undefined) {
kids[index] = obj
}
kids[index].newDob = $(this).val()
});
$(".age:checked").each(function(index, value) {
if (kids[index] == undefined) {
kids[index] = obj
}
kids[index].age = $(this).val()
});
NOTE: I haven't tested this
try this replace parent-selector-each-record with common class or id of each row
by using this approach you get exact data. also you can use #OliverRadini approach
var kids = [];
$("parent-selector-each-record").each(function() {
var kid = {};
kid["kidName"] = $(this).find(".name").val()
kid["newDob"] = $(this).find(".date_of_birth").val()
kid["age"] = $(this).find(".age:checked").val()
kids.push(kid);
});
I also suggest to reformat your object structure after that you get the data, since it will avoid some coupling with your HTML. In other words, it avoids to touch your JavaScript when you want to change your HTML.
const kids = {
kidName: ["Test1", "Test2"],
newDob: ["20/02/2000", "20/03/2018"],
age: ["19", "1"]
}
const keys = Object.keys(kids);
const result = kids[keys[0]].map((_, i) => {
return keys.reduce((obj, key) => {
obj[key] = kids[key][i];
return obj;
}, {});
});
console.log(result);

How to convert the input name dot to json format in simple way?

I have used the struts json plugin and tried to convert the form data to json format to submit by ajax.
I have two cases in the HTML
<form>
<input type="text" name="user.name" value="Tom"></p>
<input type="text" name="user.location" value="China"></p>
<input type="text" name="user.data[0].id" value="993"></p>
<input type="text" name="user.data[0].accountId" value="123"></p>
<input type="text" name="user.data[1].id" value="222"></p>
<input type="text" name="user.data[1].accountId" value="333"></p>
</form>
What I expected is to convert it to the json structure:
{
user : {
name: "Tom",
location : "China",
data: [
{
id : 993,
accountId : 123
},
{
id : 222,
accountId : 333
}
]
}
}
I know how to declare the json data and declare the attributes one by one.
I would like to have the better way to make each form to be in json format using simple way rather than declaring the parameter one by one in json format.
Appreciate for any suggestion or advice. Thank you.
Provided your form is exactly like that
Using a plain JS approach
<form class="userform">
<input type="text" class="username" value="Tom"></p>
<input type="text" class="userlocation" value="China"></p>
<input type="text" class="userid" value="993"></p>
<input type="text" class="useraccountid" value="123"></p>
<input type="text" class="userid2" value="222"></p>
<input type="text" class="useraccountid2" value="333"></p>
</form>
Then assign the values to the object
var frm = document.getElementsByClassName('userform');
//initialize blank object and keys
var user = {},
user.name = "",
user.location = "",
user.data = [];
//get all child input elements
for(var i = 0; i < frm.length; i++){
var uname = frm[i].getElementsByClassName('username')[0];
var uloc = frm[i].getElementsByClassName('userlocation')[0];
var uid = frm[i].getElementsByClassName('userid')[0];
var uaccid = frm[i].getElementsByClassName('useraccountid')[0];
var uid = frm[i].getElementsByClassName('userid2')[0];
var uaccid = frm[i].getElementsByClassName('useraccountid2')[0];
//assign values to object here
user[name] = {}; //assigning a parent property here, the name for example.
user[name].name = uname.value;
user[name].location = uloc.value;
user[name].data.push({
'id': uid.value
'accountId': uaccid.value
});
user[name].data.push({
'id': uid2.value
'accountId': uaccid2.value
});
}
JSON.stringify(user); //convert to JSON (or ignore if you want a plain object)
Output would be this in JSON format
{
user :{
Tom: {
name: "Tom",
data: [
{
id : 993,
accountId : 123
},
{
id : 222,
accountId : 333
}
]
},
Jerry: {
//more data
},
Courage: {
//more data
}
}
}
Hope this helps
If your input fields are many, like id3, accountid3, 4, 5, 6. You have to loop through the classes that you assign to these two repetitive fields
Here you go with a solution using jQuery https://jsfiddle.net/pnz8zrLx/2/
var json = {};
$('button').click(function(){
$('form').each(function(i){
json["user" + i] = {};
json["user" + i].data = [];
var tempJSON = {};
$('form:nth-child(' + (i+1) + ') input[type="text"]').each(function(){
if($(this).attr('name') === 'name' || $(this).attr('name') === 'location'){
json["user" + i][$(this).attr('name')] = $(this).val();
} else {
tempJSON[$(this).attr('name')] = $(this).val();
if(tempJSON != {} && $(this).attr('name') === 'accountId'){
json["user" + i].data.push(tempJSON);
tempJSON = {};
}
}
});
});
console.log(json);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<form>
<input type="text" name="name" value="Tom">
<input type="text" name="location" value="China">
<input type="text" name="id" value="993">
<input type="text" name="accountId" value="123">
<input type="text" name="id" value="222">
<input type="text" name="accountId" value="333">
</form>
<form>
<input type="text" name="name" value="Test">
<input type="text" name="location" value="Test112">
<input type="text" name="id" value="22">
<input type="text" name="accountId" value="78">
<input type="text" name="id" value="00">
<input type="text" name="accountId" value="44">
</form>
<button>
Submit
</button>
Hope this will help you.

Converting Form Elemnt in Javascript object

I am novice in JS , and following is the code I found on Stackoverflow itself Can someone please explain on how this serialization takes place in the function below, stepwise process? Also once the serealization is done , how to parse through the JSON object to retrieve the info in tabular form ?
JAVASCRIPT
$.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;
};
<!DOCTYPE HTML>
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<script type="text/javascript" src="demon.js"></script>
</head>
<body>
<h2>Form</h2>
<form action="" method="post">
First Name:<input type="text" name="Fname" maxlength="12" size="12"/> <br/>
Last Name:<input type="text" name="Lname" maxlength="36" size="12"/> <br/>
Gender:<br/>
Male:<input type="radio" name="gender" value="Male"/><br/>
Female:<input type="radio" name="gender" value="Female"/><br/>
Favorite Food:<br/>
Steak:<input type="checkbox" name="food[]" value="Steak"/><br/>
Pizza:<input type="checkbox" name="food[]" value="Pizza"/><br/>
Chicken:<input type="checkbox" name="food[]" value="Chicken"/><br/>
<textarea wrap="physical" cols="20" name="quote" rows="5">Enter your favorite quote!</textarea><br/>
Select a Level of Education:<br/>
<select name="education">
<option value="Jr.High">Jr.High</option>
<option value="HighSchool">HighSchool</option>
<option value="College">College</option></select><br/>
Select your favorite time of day:<br/>
<select size="3" name="TofD">
<option value="Morning">Morning</option>
<option value="Day">Day</option>
<option value="Night">Night</option></select>
<p><input type="submit" /></p>
</form>
<h2>JSON</h2>
<pre id="result">
</pre>
</body>
</html>
This is what the code is doing
// create a jQuery plugin
$.fn.serializeObject = function() {
// return object to store the values
var o = {};
// call serializeArray on the form to get [{name: 'something', value: 'something'}]
var a = this.serializeArray();
// iterate over the serialized array
$.each(a, function() {
// if the value has already been defined on the object
if (o[this.name] !== undefined) {
// check if the value is not an array
if (!o[this.name].push) {
// it's not so instantiate a new array with the value in it
o[this.name] = [o[this.name]];
}
// add the value to the array of values
o[this.name].push(this.value || '');
} else {
// we are dealing with a new value so set it to the json object
o[this.name] = this.value || '';
}
});
// return the json serialized object from the plugin
return o;
};

How to modify this json object

How do i modify this code to get the intended outcome.
This is what i get from this code.
{"name":"abc","identifier":"abc_one","number":"55","description":"This is a description"}
But i want a json object like this,
{"project":
{"name":"abc",
"identifier":"abc_one",
"number":"55",
"description":"This is a description"}
}
Please look at the code i have at the moment. It Need to be warped by a another object call "project".
$.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;
};
$(function() {
$('form').submit(function() {
$('#result').text(JSON.stringify($('form').serializeObject()));
return false;
});
});
<form action="" method="post">
First Name:<input type="text" name="name" maxlength="12" size="12"/> <br/>
Last Name:<input type="text" name="identifier" maxlength="36" size="12"/> <br/>
number:<input type="number" name="number" maxlength="36" size="12"/> <br/>
<textarea wrap="physical" cols="20" name="description" rows="5">Enter your favorite quote!</textarea><br/>
Select a Level of Education:<br/>
<p><input type="submit" /></p>
</form>
All you need to change is following
return o;
To
return {"project":o}
in serializeObject function.

Serialize HTML Form with Embedded Objects

I have the following form ...
<form id="my-form">
<fieldset name="address">
<input name="streetAddress" type="text" placeholder="Street Address"><br>
<input name="city" type="text" placeholder="City"><p>,</p>
<input name="state" type="text" placeholder="State">
<input name="zipCode" type="text" placeholder="Zip Code">
</fieldset>
<fieldset name="dimensions">
<input name="length" type="text" placeholder="length">
<input name="width" type="text" placeholder="width">
<input name="height" type="text" placeholder="height">
</fieldset>
</form>
I need to serialize it into JSON with JS, but I need to have the address's fields warped in an address object, and the dimensions's fields warped in a dimensions object.
Something like this ...
{
'address':{'streetAddress':'111 Candy Ln', 'city':'Los Angeles', ...},
'dimensions':{...}
}
How do you do this cleanly, idealy without having to write my own function for doing this? I have of course seen scripts to serialize, but nothing that will do embedded objects.
Have you tried putting all the fields into arrays?
<fieldset name="address">
<input name="address[streetAddress]" type="text" placeholder="Street Address"><br>
<input name="address[city]" type="text" placeholder="City"><p>,</p>
<input name="address[state]" type="text" placeholder="State">
<input name="address[zipCode]" type="text" placeholder="Zip Code">
</fieldset>
Heres an example, using the serializeObject plugin
Just include that script and you can convert any form into a multi layered JSON object.
DEMO HERE
Using this plugin...more info here Convert form data to JavaScript object with jQuery
(function($){
$.fn.serializeObject = function(){
var self = this,
json = {},
push_counters = {},
patterns = {
"validate": /^[a-zA-Z][a-zA-Z0-9_]*(?:\[(?:\d*|[a-zA-Z0-9_]+)\])*$/,
"key": /[a-zA-Z0-9_]+|(?=\[\])/g,
"push": /^$/,
"fixed": /^\d+$/,
"named": /^[a-zA-Z0-9_]+$/
};
this.build = function(base, key, value){
base[key] = value;
return base;
};
this.push_counter = function(key){
if(push_counters[key] === undefined){
push_counters[key] = 0;
}
return push_counters[key]++;
};
$.each($(this).serializeArray(), function(){
// skip invalid keys
if(!patterns.validate.test(this.name)){
return;
}
var k,
keys = this.name.match(patterns.key),
merge = this.value,
reverse_key = this.name;
while((k = keys.pop()) !== undefined){
// adjust reverse_key
reverse_key = reverse_key.replace(new RegExp("\\[" + k + "\\]$"), '');
// push
if(k.match(patterns.push)){
merge = self.build([], self.push_counter(reverse_key), merge);
}
// fixed
else if(k.match(patterns.fixed)){
merge = self.build([], k, merge);
}
// named
else if(k.match(patterns.named)){
merge = self.build({}, k, merge);
}
}
json = $.extend(true, json, merge);
});
return json;
};
})(jQuery);
I have two solutions for this:
Name the fields after the fieldsets (like the proposal above): address[street], address[zipcode], etc.
Give the fieldsets some unique id's.
In both cases I suggest you using this library I made: https://github.com/serbanghita/formToObject
Call it like this:
Case 1: var myFormObj = new formToObject('myFormId');
Case 2: var myFormObj = new formToObject('myFieldsetId');

Categories

Resources