Alex
Alex

Reputation: 68416

jQuery create object from form fields

How can I create a object with a form's fields and values?

like this one:

{
  fields:
   {
      name: 'foo',
      email: '[email protected]',
      comment: 'wqeqwtwqtqwtqwet'     

   }
}

assuming the form looks like this:

<form>
  <input type="text" name="name" value="foo" />
  <input type="text" name="email" value="[email protected]" />
  <textarea name="comment">wqeqwtwqtqwtqwet</textarea>
</form>

I need to know how can I do this for any form with a single function, not just a particular form.

Upvotes: 24

Views: 45535

Answers (11)

phil294
phil294

Reputation: 10852

If you want to spare any redundand element selectors, you can access the FormData from within the submit event handler function. The below code snippet will print out Object with searchTerm and includeBananas.

function submitForm(formElement) {
  const formData = new FormData(formElement)
  const allEntries = [...formData.entries()]
    .reduce((all, entry) => {
      all[entry[0]] = entry[1]
      return all
    }, {})
  console.log(allEntries)
  return false;
}
<form onsubmit="return submitForm(this)">
  <input name="searchTerm">
  <input name="includeBananas" type="checkbox">
  <button>Submit</button>
</form>

Edit: I found that this is missing one thing: FormData can hold multiple values for the same key. In that case, you would need something like

const allEntries = [...form_data.keys()].reduce((all, form_key) => {
    all[form_key] = form_data.getAll(form_key)
    return all
}, {})

Upvotes: 0

Jens H
Jens H

Reputation: 21

A lot of complicated ways which do not work in some cases. In the meantime you can use the FormData

 var fields = {};
 var myform = document.getElementById('ThisIsTheIDOfMyForm');
 var myformdata = new FormData(myform);
 for (var [key, value] of myformdata.entries()) { 
    fields[key] = value;
 }
 console.log(fields);

is exactly what you want. It handles everything.

Upvotes: 1

DDan
DDan

Reputation: 8276

Here is a simple solution:

See Demo

$(".form-sample").serializeArray().map(function(x){data[x.name] = x.value;});

Upvotes: 6

Mohammad Fazeli
Mohammad Fazeli

Reputation: 817

Simple form code

<form id="myForm" name="myForm">
    <input type="text" name="email" value="[email protected]"/>
    <input type="checkbox" name="gender">
    <input type="password" name="pass" value="123"/>
    <textarea name="message">Enter Your Message Her</textarea>
</form>

Javascript Code:

var data = {};
var element = document.getElementById("form").elements
for (var i = 0; i < element.length; i++) {
    switch (element[i].type) {
        case "text": data[element[i].name] = element[i].value; break;
        case "checkbox": data[element[i].name] = element[i].checked; break;
        case "password": data[element[i].name] = element[i].checked; break;
        case "textarea": data[element[i].name] = element[i].value; break;
    }
}

Upvotes: 0

user3504541
user3504541

Reputation: 77

This way you catch all values from multiple selects or groups of checkboxes

function form2obj(form) {
    var arr = $(form).serializeArray(), obj = {};
    for(var i = 0; i < arr.length; i++) {
        if(obj[arr[i].name] === undefined) {
            obj[arr[i].name] = arr[i].value;
        } else {
            if(!(obj[arr[i].name] instanceof Array)) {
                obj[arr[i].name] = [obj[arr[i].name]];
            }
            obj[arr[i].name].push(arr[i].value);
        }
    }
    return obj;
};

Upvotes: 1

Jordan
Jordan

Reputation: 96

So I always try to put a wrapper among form submits.

This is especially important for form submits that run over ajax.

The first thing to do is grab the form on submit.

$(".ajax-form").submit(function(){
    var formObject = objectifyForm($(this).serializeArray());
    // Do stuff with formObject 

    // always add return false to stop the form from actually doing a post anywhere
    return false;
});

This will wrap any form that has a class of "ajax-form" and send the serializeArray to a function that is called objectify form which will return an object of all of the values of that form.

function objectifyForm(formArray) {
    returnArray = {};
    for (var i = 0; i < formArray.length; i++) {
        returnArray[formArray[i]['name']] = formArray[i]['value'];
    }
    return returnArray;
}

Upvotes: 0

T.J. Crowder
T.J. Crowder

Reputation: 1074168

You can do this:

var fields = {};
$("#theForm").find(":input").each(function() {
    // The selector will match buttons; if you want to filter
    // them out, check `this.tagName` and `this.type`; see
    // below
    fields[this.name] = $(this).val();
});
var obj = {fields: fields}; // You said you wanted an object with a `fields` property, so...

Beware that forms can have fields with repeated names, and what you're trying to do doesn't support that. Also, the order of fields in HTML forms can be significant. (These are both reasons that serializeArray works the way it does.)

Note that normal HTML practice is to omit disabled fields. If you want to do that, check this.disabled before grabbing the value as well.


Note that the above (written two years ago) uses a jQuery pseudo-selector. I'm a bit surprised to find that I wrote that. As it says in the documentation for the :input pseudo-selector, using it means that jQuery can't hand off the selector to the browser's native querySelectorAll (which nearly all browsers now have).

Nowadays I'd probably write:

$("#theForm").find("input, textarea, select, button")...

...if I wanted buttons, or if not then

$("#theForm").find("input, textarea, select")...

...and then filter out input[type="button"] and input[type="submit"] inside the each. E.g. (no buttons at all):

$("#theForm").find("input, textarea, select").each(function() {
    var inputType = this.tagName.toUpperCase() === "INPUT" && this.type.toUpperCase();
    if (inputType !== "BUTTON" && inputType !== "SUBMIT") {
        // ...include it, either it's an `input` with a different `type`
        // or it's a `textarea` or a `select`...
    }
});

Upvotes: 41

Hussein
Hussein

Reputation: 42808

var inputs = $("form :input");
var obj = $.map(inputs, function(x, y) {
    return {
        Key: x.name,
        Value: $(x).val()
    };
});
console.log(obj);

Upvotes: 11

albb
albb

Reputation: 234

jquery has a serialize() function on froms like $('#myform').serialize()

is this what you're looking for?

update: oops, maybe try serializeArray() instead, it should give you an array of name and value.

Upvotes: 3

Brett Zamir
Brett Zamir

Reputation: 14345

As per a comment on the http://api.jquery.com/serializeArray/ page, you can do:

(function( $ ){
    $.fn.serializeJSON=function() {
        var json = {};
        jQuery.map($(this).serializeArray(), function(n, i){
            json[n['name']] = n['value'];
        });
        return json;
    };
})( jQuery );

Then do:

var obj = $('form').serializeJSON();

or if you need it with your fields property, you can modify the function or do this:

var obj = {fields: $('form').serializeJSON()};

Or you can just use serializeArray() if you don't mind that format of output.

Upvotes: 6

gion_13
gion_13

Reputation: 41533

function formsToObj(){
    var forms = [];
    $('form').each(function(i){
        forms[i] = {};
        $(this).children('input,textarea,select').each(function(){
            forms[i][$(this).attr('name')] = $(this).val();
        });
    });
    return forms;
}

it's a generalized function that creates an object for each form in your page

Upvotes: 1

Related Questions