1

Consider the following pairs of inputs

<input type="text" class="item_name" value="iphone">
<input type="text" class="item_qty" value="10">

<input type="text" class="item_name" value="macbook">
<input type="text" class="item_qty" value="5">

The number of pairs of inputs on a page is dynamic, not fixed.

I wish to loop through all pairs and store values as pairs to be output later into a table for example.

I've been trying to do it with jQuery's each() but I can't figure it out fully.

  var detail = [];
  //var detail = {};

   $('input').each(function(index) {
      detail[index] = $(this).val();
      //detail.index = $(this).val();
   });

  console.log(detail);

This outputs

["iphone", "10", "macbook", "5"]

And it's not what I need.

I'm used to PHP, so what is the correct approach in JS/jQuery to store the pairs of inputs as a multidimensional associative array/object?

ProEvilz
  • 5,310
  • 9
  • 44
  • 74

5 Answers5

3

You can iterate over the elements with class item_name and create an array of objects that each have a name and qty property.

You can create this array more easily using jQuery's .map():

var details = $('.item_name').map(function() {
  return {
    name: $(this).val(),
    qty: $(this).next('.item_qty').val()
  };
}).get();

console.log(details);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="text" class="item_name" value="iphone">
<input type="text" class="item_qty" value="10">

<input type="text" class="item_name" value="macbook">
<input type="text" class="item_qty" value="5">
4castle
  • 32,613
  • 11
  • 69
  • 106
1

The equivalent of an associative array in javascript is an object (both act as a dictionary)

The problem you have is that your html describes a key and a value as inputs in a flat list, so when you enumerate them with your JQuery .each() you get them back all in one list.

[key, value, key, value]

what you most likely want is an object like:

var obj = {
  key: value,
  key: value
}

Then you can get at say the 'macbook' property like so

obj.macbook or obj['macbook']

You can achieve this by either looping through the list two at a time and adding them to the object, or by restructing your html to have both the key and value inputs inside another element e.g.

<div class="item">
 <input type="text" class="item_name" value="iphone">
 <input type="text" class="item_qty" value="10">
</div>
<div class="item">
 <input type="text" class="item_name" value="macbook">
 <input type="text" class="item_qty" value="5">
</div>

Then you can do something like this:

var items = {}
$('.item').each(function(){
 var key = $(this).find('.item_name').val()
 var value = $(this).find('.item_qty').val()
 items[key] = value;
})
dpix
  • 2,765
  • 2
  • 16
  • 25
0

var val = $("input.item_name").map(function(){
obj = {}

obj[$(this).val()] = $(this).next("input.item_qty").val();

return obj;
}).get()

console.log(val)
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="text" class="item_name" value="iphone">
<input type="text" class="item_qty" value="10">

<input type="text" class="item_name" value="macbook">
<input type="text" class="item_qty" value="5">

Use .map()

guradio
  • 15,524
  • 4
  • 36
  • 57
  • With a structure like this, it would perhaps be more reasonable to output just a single object, with many keys, instead of an array of objects which each has one key. – 4castle Feb 13 '17 at 02:14
  • That's a good point. What are the pro's and con's of each @4castle? – ProEvilz Feb 13 '17 at 02:17
  • @ProEvilz Arrays allow duplicate elements, while objects require each key to be unique in the object. Arrays are much easier to consume, because there are many built-in [utility functions](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array) for manipulating and iterating their contents. – 4castle Feb 13 '17 at 02:26
0

You can use recursion, Array.prototype.slice() to slice two <input> elements at each function call, populate an object with key, value pairs until <input> elemnents .length is reached

var [obj, n] = [{}, 2];
var inputs = $("input[type=text]");
var res = (function re(i) {
  if (i + n <= inputs.length) {
    var [key, prop] = Array.from(inputs).slice(i, i + n).map(({value}) => value)
    obj[key] = prop;
    i += n;
    return re(i)  
  } else {
    return obj
  }
})(0);
console.log(res)
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="text" class="item_name" value="iphone">
<input type="text" class="item_qty" value="10">

<input type="text" class="item_name" value="macbook">
<input type="text" class="item_qty" value="5">
guest271314
  • 1
  • 15
  • 104
  • 177
  • Many people who use jQuery do so because of its browser compatibility. This answer uses several features from ES6, which has lower browser compatibility and will need to be transpiled with something like [Babel](https://babeljs.io/) to work on older browsers. – 4castle Feb 13 '17 at 02:24
  • @4castle The Answer is to illustrate a possible pattern which could be used to return expected result. Do you suggest editing Answer to remove destructuring assignments? When browser issues arise as to compatibility, the first impression here would be to suggest updating browser. – guest271314 Feb 13 '17 at 02:26
  • I think using ES6 features in answers is a great practice, because it teaches people about new features. I just think it's important to leave a note about how to make it work with older browsers. – 4castle Feb 13 '17 at 02:28
  • @ProEvils Note, destructuring assignments at Answer can be replaced with `var obj = {}; var n = 2;` at `Array.from()` with `var arr = Array.prototype.slice.call(inputs, i, i + n).map(function(o) {return o.value})`, `var key = arr[0]; var prop = arr[1]` – guest271314 Feb 13 '17 at 02:36
-1

You can try a quick and "dirty" solution:

Ref: for each input type get value with javascript

You were on the right track with .getElementById, but you want instead, .getElementsByName.

var els = document.getElementsByName("filter[]");

for (var i = 0; i < els.length; i++)
  alert(els[i].value);
<input id="filter_15" type="checkbox" name="filter[]" value="15">
<input id="filter_16" type="checkbox" name="filter[]" value="16">
<input id="filter_17" type="checkbox" name="filter[]" value="17">

Or, follow this: jQuery .each() with input elements

To extract number :

var arrNumber = new Array();
$('input[type=number]').each(function(){
    arrNumber.push($(this).val());
})

To extract text:

var arrText= new Array();
$('input[type=text]').each(function(){
    arrText.push($(this).val());
})

Edit : .map implementation

var arrText= $('input[type=text]').map(function(){
    return this.value;
}).get();
  • opps! I copy your text but it's is broken in my comment!! – Tran Manh Quy Feb 13 '17 at 01:58
  • I'm not specifically looking for a way to output them, but a way to store them in an array or as an object, of which I can then output. The detail.name part was just an example of how I would want to write it to give more clarity of the type of loop needed – ProEvilz Feb 13 '17 at 01:59
  • I think y need create an object to store value. So you can get it from array and use obj.attribute.. – Tran Manh Quy Feb 13 '17 at 02:02