Alain Jacomet Forte
Alain Jacomet Forte

Reputation: 4685

Looping through a set of HTML form elements to get the current values in an object

Taking from a HTML setup that looks like this:

   <nav data-filters class="">

        <input type="radio" name="type" value="company" checked>Company
        <input type="radio" name="type" value="product">Product
        <input type="radio" name="type" value="service">Service

        <select name="category_1" multiple>
            <option value="a" selected>a</option>
            <option value="b">b</option>
            <option value="c" selected>c</option>
        </select>

        <select name="category_2" multiple>
            <option value="a" selected>a</option>
            <option value="b" selected>b</option>
            <option value="c">c</option>
        </select>

        <input type="radio" name="startswith" value="a" checked>a
        <input type="radio" name="startswith" value="b">b
        <input type="radio" name="startswith" value="c">c
        <input type="radio" name="startswith" value="num">#

        <input name="keyword" type="text">

    </nav>

The goal is to achieve this result:

obj = {

   "type": {
        "values": [
            "company"
        ]
    },
    "category_1": {
        "values": [
            "a",
            "c"
        ]
    },
    "category_2": {
        "values": [
            "a",
            "b"
        ]
    },
    "startswith": {
        "values": [
            "a"
        ]
    }
}

This is my current setup ( note: this.$el just refers to $(nav) ):

        var obj = {};

        this.$el.find('[name]').each(function(i, input) {

                var val     = (function() {
                                if ( input.type == "radio" || input.type == "checkbox" )
                                    return $(input).filter(':checked').val();

                                return $(input).val()
                                })(),
                    name    = input.name;

                if (val) {
                    obj[name] = {
                        values: _.flatten([val]) // Always return an array
                    }
                }
            });

        return obj;

This seems error prone, and I don't think it's the best way to do it. How should I really be doing this?

Notes on the background of this question: I'm building a small directory with backbone. This happens in the Filters view, where the current criteria is turned into an object, which is going to be passed to the collection as data for the fetch() function.

Upvotes: 0

Views: 340

Answers (1)

lukaszfiszer
lukaszfiszer

Reputation: 2631

You can use $.serializeArray method (https://api.jquery.com/serializeArray/) to serialize your form into an array of names and values. Then you just need to convert the result to the desired form:

var inputs = $('nav :input').serializeArray();
var obj = {};
_.each(inputs, function(val){
  if(obj[val.name]){
     obj[val.name].values.push(val.value);
  }else{
    obj[val.name] = {values: [val.value]};
  }
});

JSBin demo: http://jsbin.com/zidanata/2/edit?html,js,console

Upvotes: 1

Related Questions