This question already has answers here: Convert form data to JavaScript object with jQuery (59 answers) Closed 7 years ago.
I want to do some pre-server-validation of a form in a Backbone.js model. To do this I need to get the user input from a form into usable data. I found three methods to do this:
var input = $("#inputId").val(); var input = $("form.login").serialize(); var input = $("form.login").serializeArray();
Unfortunately, none of the provide a good reabable and developable JSON object which I require. I already looked through several questions on Stack Overflow, but I found only some extra libraries.
Doesn't Underscore.js, the current jQuery or Backbone.js provide a helper method?
I can't imagine there is no request for such a function.
HTML
<form class="login">
<label for="_user_name">username:</label>
<input type="text" id="_user_name" name="user[name]" value="dev.pus" />
<label for="_user_pass">password:</label>
<input type="password" id="_user_pass" name="user[pass]" value="1234" />
<button type="submit">login</button>
</form>
JavaScript
var formData = $("form.login").serializeObject();
console.log(formData);
Outputs
{
"name": "dev.pus",
"pass": "1234"
}
Backbone.js model
var user = new User(formData);
user.save();
.serializeArray()
?
This question already has an answer here:
: JSON is not JavaScript object, its serialized object!
Here's a function for this use case:
function getFormData($form){
var unindexed_array = $form.serializeArray();
var indexed_array = {};
$.map(unindexed_array, function(n, i){
indexed_array[n['name']] = n['value'];
});
return indexed_array;
}
Usage:
var $form = $("#form_data");
var data = getFormData($form);
You can do this:
function onSubmit( form ){ var data = JSON.stringify( $(form).serializeArray() ); // <----------- console.log( data ); return false; //don't submit }
see this: http://www.json.org/js.html
name=foo value=boo
pairs instead of just foo=boo
- answer from @Maciej Pyszyński seems more appropriate
The below code should help you out. :)
//The function is based on http://css-tricks.com/snippets/jquery/serialize-form-to-json/
<script src="//code.jquery.com/jquery-2.1.0.min.js"></script>
<script>
$.fn.serializeObject = function() {
var o = {};
var a = this.serializeArray();
$.each(a, function() {
if (o[this.name]) {
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.login').on('submit', function(e) {
e.preventDefault();
var formData = $(this).serializeObject();
console.log(formData);
$('.datahere').html(formData);
});
});
</script>
Use:
var config = {};
jQuery(form).serializeArray().map(function(item) {
if ( config[item.name] ) {
if ( typeof(config[item.name]) === "string" ) {
config[item.name] = [config[item.name]];
}
config[item.name].push(item.value);
} else {
config[item.name] = item.value;
}
});
I know this doesn't meet the helper function requirement, but the way I've done this is using jQuery's $.each() method
var loginForm = $('.login').serializeArray();
var loginFormObject = {};
$.each(loginForm,
function(i, v) {
loginFormObject[v.name] = v.value;
});
Then I can pass loginFormObject to my backend, or you could create a userobject and save() it in backbone as well.
loginForm
contained both inputs (if the checkbox was checked, false
only otherweise) and loginFormObject
afterwards got the second input, which was always false
. Solution here: in the sub-function of the each
, add the following line after the {
: if(formObject[v.name] != "true")
. This will preserve the true
.
Trying to solve the same problem (validation without getting into complex plugins and libraries), I created jQuery.serializeJSON, that improves serializeArray to support any kind of nested objects.
This plugin got very popular, but in another project I was using Backbone.js, where I would like to write the validation logic in the Backbone.js models. Then I created Backbone.Formwell, which allows you to show the errors returned by the validation method directly in the form.
I couldn't find an answer that would solve this:
[{name:"Vehicle.Make", value: "Honda"}, {name:"Vehicle.VIN", value: "123"}]
This calls for this object:
{Vehicle: {Make: "Honda", "VIN": "123"}}
So I had to write a serializer of my own that would solve this:
function(formArray){
var obj = {};
$.each(formArray, function(i, pair){
var cObj = obj, pObj, cpName;
$.each(pair.name.split("."), function(i, pName){
pObj = cObj;
cpName = pName;
cObj = cObj[pName] ? cObj[pName] : (cObj[pName] = {});
});
pObj[cpName] = pair.value;
});
return obj;
}
Maybe it will help somebody.
If you do not care about repetitive form elements with the same name, then you can do:
var data = $("form.login").serializeArray();
var formData = _.object(_.pluck(data, 'name'), _.pluck(data, 'value'));
I am using Underscore.js here.
Here is what I use for this situation as a module (in my formhelper.js):
define(function(){
FormHelper = {};
FormHelper.parseForm = function($form){
var serialized = $form.serializeArray();
var s = '';
var data = {};
for(s in serialized){
data[serialized[s]['name']] = serialized[s]['value']
}
return JSON.stringify(data);
}
return FormHelper;
});
It kind of sucks that I can't seem to find another way to do what I want to do.
This does return this JSON for me:
{"first_name":"John","last_name":"Smith","age":"30"}
If you are sending the form with JSON you must remove [] in the sending string. You can do that with the jQuery function serializeObject():
var frm = $(document.myform);
var data = JSON.stringify(frm.serializeObject());
$.fn.serializeObject = function() {
var o = {};
// var a = this.serializeArray();
$(this).find('input[type="hidden"], input[type="text"], input[type="password"], input[type="checkbox"]:checked, input[type="radio"]:checked, select').each(function() {
if ($(this).attr('type') == 'hidden') { //if checkbox is checked do not take the hidden field
var $parent = $(this).parent();
var $chb = $parent.find('input[type="checkbox"][name="' + this.name.replace(/\[/g, '\[').replace(/\]/g, '\]') + '"]');
if ($chb != null) {
if ($chb.prop('checked')) return;
}
}
if (this.name === null || this.name === undefined || this.name === '')
return;
var elemValue = null;
if ($(this).is('select'))
elemValue = $(this).find('option:selected').val();
else elemValue = this.value;
if (o[this.name] !== undefined) {
if (!o[this.name].push) {
o[this.name] = [o[this.name]];
}
o[this.name].push(elemValue || '');
} else {
o[this.name] = elemValue || '';
}
});
return o;
}
Using Underscore.js:
function serializeForm($form){
return _.object(_.map($form.serializeArray(), function(item){return [item.name, item.value]; }));
}
Using jQuery and avoiding serializeArray
, the following code serializes and sends the form data in JSON format:
$("#commentsForm").submit(function(event){
var formJqObj = $("#commentsForm");
var formDataObj = {};
(function(){
formJqObj.find(":input").not("[type='submit']").not("[type='reset']").each(function(){
var thisInput = $(this);
formDataObj[thisInput.attr("name")] = thisInput.val();
});
})();
$.ajax({
type: "POST",
url: YOUR_URL_HERE,
data: JSON.stringify(formDataObj),
contentType: "application/json"
})
.done(function(data, textStatus, jqXHR){
console.log("Ajax completed: " + data);
})
.fail(function(jqXHR, textStatus, errorThrown){
console.log("Ajax problem: " + textStatus + ". " + errorThrown);
});
event.preventDefault();
});
Well, here's a handy plugin for it: https://github.com/macek/jquery-serialize-object
The issue for it is:
Moving ahead, on top of core serialization, .serializeObject will support correct serializaton for boolean and number values, resulting valid types for both cases. Look forward to these in >= 2.1.0
My contribution:
function serializeToJson(serializer){
var _string = '{';
for(var ix in serializer)
{
var row = serializer[ix];
_string += '"' + row.name + '":"' + row.value + '",';
}
var end =_string.length - 1;
_string = _string.substr(0, end);
_string += '}';
console.log('_string: ', _string);
return JSON.parse(_string);
}
var params = $('#frmPreguntas input').serializeArray();
params = serializeToJson(params);
Found one possible helper:
https://github.com/theironcook/Backbone.ModelBinder
and for people who don't want to get in contact with forms at all: https://github.com/powmedia/backbone-forms
I will take a closer look at the first link and than give some feedback :)
Success story sharing
somefield[2] => [somefield][2]
and use eval to assign valueeval('you_array_varialbe'+bracketed_field_name+'=\''+n['value']+'\'')