17

I'm trying to loop over input elements in div, to create an array of objects

<div id="time">
  <input type="text" name="from" placeholder="12:00 AM" />
  <input type="text" name="to" placeholder="12:30 AM" />
  <input type="text" name="from" placeholder="13:00 AM" />
  <input type="text" name="to" placeholder="13:30 AM" />
</div>

I'm trying to create the following array of objects.

 unavailability: [
      { from: '12:00', to: '12:30' },
      { from: '13:00', to: '13:30' }
    ]

Here is what I have tried so far, but result is quite different.

var dataArray = []
$("#time").find('input').each(function() {
  var data = {};

  data[this.name] = this.value
  dataArray.push(data);

});
console.log(dataArray)
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="time">
  <input type="text" name="from" placeholder="12:00 AM" />
  <input type="text" name="to" placeholder="12:30 AM" />
  <input type="text" name="from" placeholder="13:00 AM" />
  <input type="text" name="to" placeholder="13:30 AM" />
</div>

JSFiddle

Vickel
  • 7,879
  • 6
  • 35
  • 56
Deano
  • 11,582
  • 18
  • 69
  • 119
  • You should not have multiple inputs with the same `name` attribute in the same `
    `. (Unless for radio buttons)
    – Bergi Jan 17 '18 at 14:49

7 Answers7

12

You may iterate over all the elements having name attribute value as from. To get the to value, use next() method of jQuery.

Use .val() method to get the value of item.

$('#submit').click(function() {
  var data = [];

  $('#time input[name="from"]').each(function() {
    data.push({
      from: $(this).val(),
      to: $(this).next().val()
    });
  });

  console.log(data);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Enter times in the below textboxes
<div id="time">
  <input type="text" name="from" placeholder="12:00 AM" />
  <input type="text" name="to" placeholder="12:30 AM" />
  <input type="text" name="from" placeholder="13:00 AM" />
  <input type="text" name="to" placeholder="13:30 AM" />
</div>

<button id="submit">Submit</button>
Tushar
  • 85,780
  • 21
  • 159
  • 179
10

I would have solved it with FormData. It means less DOM navigation and less chance of doing something wrong if you change the markup later. This also means you would have to change your div element to a form element (unless you have it somewhere higher up - in that case you could use that form element in the constructor and keep the div element):

// Get a formdata instance
var fd = new FormData(time)

// Get all values
var from = fd.getAll('from')
var to = fd.getAll('to')

// Transform
var unavailable = from.map((from, i) => ({ from, to: to[i] }))

console.log({unavailable})
<form id="time">
  <input type="text" name="from" placeholder="12:00 AM" value="12:00" />
  <input type="text" name="to" placeholder="12:30 AM"  value="12:30" />
  <input type="text" name="from" placeholder="13:00 AM" value="13:00" />
  <input type="text" name="to" placeholder="13:30 AM" value="13:30" />
</form>

BTW, you are mixing 12/24 hours (13:00). It should maybe be written as 1:00 pm(?).

I would also have changed the type to type="time" to avoid mistakes. It gives you a nice time picker and it does normalize the value if the user enters a 12 or 24 hour value. You would also then be able to use step/min/max/required for better validation if you would need it

Endless
  • 34,080
  • 13
  • 108
  • 131
  • Should `var fd = new FormData(time)` be `...('time')`? – TripeHound Jan 17 '18 at 14:05
  • in this case yes (if you are lazy), Normally you would do `var time = document.getElementById('time')` but any element with a id that don't have it's name on the global window scope can be accessed from `window`. Read [this QA](https://stackoverflow.com/questions/3434278/do-dom-tree-elements-with-ids-become-global-variables). It's a bit of risky but for the sake of this simple demo i choosed to use `...('time')` – Endless Jan 17 '18 at 14:37
4

Instead of iterating over each input, you need to iterate over every alternate input element with name attribute equal to form. Then create the JSON information for the element you are iterating on and immediate next sibling input element.

Also 12.30 am is not the value of the element, its placeholder. You need to replace the value with a placeholder:

$("#time").find('input[name="from"]').each(function() {
    var data = {};
    data[this.name] = this.placeholder;
    var nextInput = $(this).next()[0];
    data[nextInput .name] = nextInput.placeholder;
    dataArray.push(data);
});

Working Demo

The best way to achieve this is to use the jQuery .map() function returning the JSON object along with .get() to create array of JSON objects:

var dataArray = $("#time").find('input[name="from"]').map(function() {
    var nextInput = $(this).next()[0];
    var jo = {};
    jo[this.name]=this.placeholder;jo[nextInput.name] = nextInput.placeholder
    return jo;
}).get();

var dataArray = $("#time").find('input[name="from"]').map(function() {
    var nextInput = $(this).next()[0];
    var jo = {};
    jo[this.name]=this.placeholder;jo[nextInput.name] = nextInput.placeholder
    return jo;
}).get();

console.log(dataArray)
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="time">
  <input type="text" name="from" placeholder="12:00 AM" />
  <input type="text" name="to" placeholder="12:30 AM" />
  <input type="text" name="from" placeholder="13:00 AM" />
  <input type="text" name="to" placeholder="13:30 AM" />
</div>
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Milind Anantwar
  • 81,290
  • 25
  • 94
  • 125
3

You can do that in the following way:

var unavailability = [];
$('#time input[name=from]').each(function(i, input){
  unavailability.push({
    from: $(this).attr('placeholder').split(' ')[0],
    to: $(this).next().attr('placeholder').split(' ')[0]
  });
});

console.log(unavailability);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="time"> 
  <input type="text" name="from" placeholder="12:00 AM" />
  <input type="text" name="to" placeholder="12:30 AM" />
  <input type="text" name="from" placeholder="13:00 AM" />
  <input type="text" name="to" placeholder="13:30 AM" />
</div>
Mamun
  • 66,969
  • 9
  • 47
  • 59
1
var dataArray = [];
$("#time").find('input[name="from"]').each(function() {
    var data = {};
    data.from = this.value;
    data.to = $(this).next().val();
    dataArray.push(data);
});

console.log(dataArray);

Updated fiddle

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Lalit
  • 1,354
  • 1
  • 8
  • 13
1

Here either you need to use an event handler for change in values of any input or you need to give some initial values to these inputs.

Also you can iterate as shown below to get the desired result.

var dataArray = [];
var data = {};
$("#time").find('input').each(function(i) {
    if(i%2 === 0){
      data={};
      data[this.name] = this.value;
    } else{
      data[this.name] = this.value;
     dataArray.push(data);
    }
});

console.log(dataArray);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="time"> 
  <input type="text" name="from" placeholder="12:00 AM" value="12:00 AM" />
  <input type="text" name="to" placeholder="12:30 AM" value="12:30 AM" />
  <input type="text" name="from" placeholder="13:00 AM" value="13:00 AM" />
  <input type="text" name="to" placeholder="13:30 AM" value="13:30 AM" />
</div>

<span id="output"></span>
Rohit Agrawal
  • 1,496
  • 9
  • 20
0

In my answer I push new item to array only if this.name === "from". If this.name === "to", I add new property to the last pushed item, and finally we have 2 objects in array and 2 properties in each object:

$("#btn").click(doStuff);

function doStuff() {
  var dataArray = []
  var newArrayLength;
  $("#time").find('input').each(function() {
    if (this.name === "from") {
      var data = {};
      data[this.name] = this.value 
      newArrayLength = dataArray.push(data);
    } else if (this.name === "to") {
      dataArray[newArrayLength - 1][this.name] = this.value; 
    }
  });
  console.log(dataArray);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="time"> 
  <input type="text" name="from" placeholder="12:00 AM" />
  <input type="text" name="to" placeholder="12:30 AM" />
  <input type="text" name="from" placeholder="13:00 AM" />
  <input type="text" name="to" placeholder="13:30 AM" />
</div>

<span id="output"></span>

<button id="btn">Click</button>

https://jsfiddle.net/ss725ere/2/

P.S.
  • 15,970
  • 14
  • 62
  • 86