Tamb
Tamb

Reputation: 748

How do I store <input> "names" as properties of an object and then store the matching <input> "value" as the values of that object's properties?

I'm looking to essentially build an object dynamically where a property be the inputs name and the value of that property will be the inputs value.

Here's HTML

<form>
                <fieldset>
                    <legend>form</legend>
                    <label>First<input type="text" value="null" name="first"/></label>
                    <label>Last<input type="text" value="null" name="last"/></label>
                    <label>Email<input type="text" value="null" name="email"/></label>

                    <input type="submit" value="submit"/>
                </fieldset>
            </form>

Here's the jQuery I'm using so far.
I have stored the values in and names in separate arrays. Is there a way to create some sort of associative array or to create an object where property names are taken from one array and values taken from another?

        var values = new Array();
    var names = new Array();

    $("form").submit(function(event){
        event.preventDefault();

            values = [];
            names = [];

            $('form input').not('[type="submit"]').each(function(){
            values.push($(this).val());

            });


            $('form input').not('[type="submit"]').each(function(){
            names.push($(this).attr("name"));

            });

    });

I've also tried the .serializeArray() and it returns an array of Objects. But then I have no idea how to pull all of the key/value pairs out of that object and into a new one.

The end goal is to not send this data over ajax but to send to a third party that aggregates data for analytics. Please help. I'm self taught and totally lost. Haha. Thanks

PS

I tried this

$( "form" ).on( "submit", function( event ) {
            event.preventDefault();
            var input = $("form").serializeArray();
            $.each(input, function(i, field){
                console.log(JSON.stringify(input[i]));
            });
        });

but it returns this

{"name":"first","value":"null"}
{"name":"last","value":"null"}
{"name":"email","value":"null"}

which seems to be equally as unhelpful. Haha.

I would love to be able to get an outcome as such

{
  "first" : "null",
  "last" : "null",
  "email" : "null"
}

Upvotes: 2

Views: 2952

Answers (3)

Phil
Phil

Reputation: 164812

Easiest way I can think of is to use serializeArray and then reduce that to an object or map. For example

$('form').on('submit', e => {
    e.preventDefault();

    let values = $(this).serializeArray().reduce((map, input) => {
        let value;
        if (map.hasOwnProperty(input.name)) {
            value = Array.isArray(map[input.name]) ?
                map[input.name] : [map[input.name]];
            value.push(input.value);
        } else {
            value = input.value;
        }
        map[input.name] = value;
        return map;
    }, {});
})

This handles <select multiple> and <input type="checkbox"> elements by setting the named value as an array.

JSFiddle demo here ~ https://jsfiddle.net/wmjeh5Lv/1/


Legacy version

$('form').on('submit', function(e) {
    e.preventDefault();

    var values = $(this).serializeArray().reduce(function(map, input) {
        var value;
        if (map.hasOwnProperty(input.name)) {
            value = Array.isArray(map[input.name]) ?
                map[input.name] : [map[input.name]];
            value.push(input.value);
        } else {
            value = input.value;
        }
        map[input.name] = value;
        return map;
    }, {});
})

Upvotes: 2

Jhecht
Jhecht

Reputation: 4435

This should work, though realistically I don't understand the need for it. Check your browser's console. It gave me: {first: "null", last: "null", email: "null"}

$(document).ready(function() {
  $('form').on('submit', function(e) {
    e.preventDefault();
    var arrObj = {};
    $(this).find('input:not(:submit)').each(function(i, el) {
      el = $(el);
      arrObj[el.attr('name')] = el.val();
    });
    console.log(arrObj);
  })
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<form>
  <fieldset>
    <legend>form</legend>
    <label>First
      <input type="text" value="null" name="first" />
    </label>
    <label>Last
      <input type="text" value="null" name="last" />
    </label>
    <label>Email
      <input type="text" value="null" name="email" />
    </label>

    <input type="submit" value="submit" />
  </fieldset>
</form>
<div id="results">
</div>

Quick bit about Scope and Functions

Note: I am not a javascript expert, I have no formal education on it these are simply the things I've learned in using javascript.

  1. If you define a variable outside a function, you can use it inside*

Using the same code I gave you, you could do something like this:

$(document).ready(function() {
  var arrObj = {};
  //Notice, arrObj is now defined OUTSIDE of our form.onsubmit function
  $('form').on('submit', function(e) {
    e.preventDefault();

    $(this).find('input:not(:submit)').each(function(i, el) {
      el = $(el);
      arrObj[el.attr('name')] = el.val();
    });
    console.log(arrObj);
  });

  $('button').on('click', function() {
    console.log(arrObj);
  });
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<form>
  <fieldset>
    <legend>form</legend>
    <label>First
      <input type="text" value="null" name="first" />
    </label>
    <label>Last
      <input type="text" value="null" name="last" />
    </label>
    <label>Email
      <input type="text" value="null" name="email" />
    </label>

    <input type="submit" value="submit" />
  </fieldset>
</form>

<button>Click me and Check Console<small>*Must click submit button first</small></button>

  1. This goes up as far as you want it to.

Got a variable you defined outside the $(document).ready(...) and you want to use it? Go ahead. Javascript don't care.

  1. When in doubt, create another function that you can return from somewhere else, like so (this involves using $.fn.extend() to add a new method to every jquery object)

$.fn.extend({
  formObject: function() {
    var arrObj = {};
    
    $(this).find('input:not(:submit)').each(function(i, el) {
      el = $(el);
      arrObj[el.attr('name')] = el.val();
    });
    return arrObj;
  }
});

$(document).ready(function() {

  $('button').on('click', function() {
    alert('check console');
    console.log($('form').formObject());
  });
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<form>
  <fieldset>
    <legend>form</legend>
    <label>First
      <input type="text" value="null" name="first" />
    </label>
    <label>Last
      <input type="text" value="null" name="last" />
    </label>
    <label>Email
      <input type="text" value="null" name="email" />
    </label>
  </fieldset>
</form>

<button>Click Me</button>

These are not the only ways, and if I am honest I don't even think they're the best ways, but they're the fastest ways using what we already have.

Upvotes: 1

j3ff
j3ff

Reputation: 6089

I don't understand why the submit button if the only need it go generate an object?

So here is my try only to generate the output without arrays ...

function generate() {

  var obj = {};
  
  $('form input').not('[type="submit"]')
    .each((index, input) => obj[input.name] = input.value);
  
  $('#result').text(JSON.stringify(obj));
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.3/jquery.min.js"></script>
<form>
  <fieldset>
    <legend>form</legend>
    <label>First<input type="text" value="null" name="first"/></label>
    <label>Last<input type="text" value="null" name="last"/></label>
    <label>Email<input type="text" value="null" name="email"/></label>

    <button onclick="generate()">Generate</button>
  </fieldset>
</form>

<br>
<div id="result"></div>

Upvotes: 0

Related Questions