Styphon Styphon - 17 days ago 4
jQuery Question

Convert mutlidimensional inputs to JavaScript object

I've been trying to solve this one for several days now and it's driving me nuts. I have some data that needs to be submitted by Ajax. It is dynamic, so I don't know how many fields it has. On top of that the names of the fields are multidimensional and also dynamic. For example one might have inputs with the name

data[name]
and
data[title]
whilst another larger one might have
data[images][0][src]
,
data[images][0][alt]
,
data[images][0][description]
,
data[images][1][src]
,
data[images][1][alt]
,
data[images][1][description]
with an unknown number of elements to the array. My problem is that I need to get an object I can submit via Ajax whilst maintaining the structure of the data.

I've tried serialising the data, but that just comes up with a string of
name = value
. I've tried serialise array as well, but that just gives me an array of
[name, value]
. I've managed to generate the object manually using a regex to split it up, but I can't find a way to merge the resultant objects together. The latest version of my code is:

$('.modal-content').find('input[name^="data"]').each(function () {
var found = $(this).attr('name').match(re).reverse();
var temp = $(this).val();
$.each(found, function ()
{
str = this.substr(1, this.length - 2);
var t = {};
t[str] = temp;
temp = t;
});
data = $.each({}, data, temp);
});


Unfortunately it doesn't merge them, it overwrites what is in data with what is in temp. If data has
data.images[0].src = "mysrc"
and temp has
data.images[0].alt = "myalt"
then I just end up with
data.images[0].alt = "myalt"
and src is no longer there.

There has to be a simple way to do this, hell at this point I'd even take a complicated way to do this. Can someone please help me with this?

Answer

You can loop all inputs with each() loop, create array from name attributes using split() and then use reduce to add to object

var result = {}

$('input').each(function() {
  var name = $(this).attr('name');
  var val = $(this).val();

  var ar = name.split(/\[(.*?)\]/gi).filter(e => e != '');

  ar.reduce(function(a, b, i) {
    return (i != (ar.length - 1)) ? a[b] || (a[b] = {}) : a[b] = val;
  }, result)

})

console.log(result)
.as-console-wrapper { max-height: 100% !important; top: 0; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul id="gallery-images" class="ui-sortable">
  <li class="col-xs-12 col-sm-6 col-md-4 col-lg-3 gallery-image ui-sortable-handle">
    <div>
      <img src="http://localhost:8000/img/example.jpg">
      <input type="hidden" name="data[images][0][src]" value="img/example.jpg">
      <div class="form-group">
        <label for="title-0">Title:</label>
        <input type="text" name="data[images][0][title]" class="form-control" id="title-0" value="Default Example Image 1" placeholder="Title">
      </div>
      <div class="form-group">
        <label for="description-0">Description:</label>
        <input type="text" name="data[images][0][description]" class="form-control" id="description-0" value="A default example image." placeholder="Description">
      </div>
      <div class="form-group">
        <label for="alt-0">Alt tag (SEO):</label>
        <input type="text" name="data[images][0][alt]" class="form-control" id="alt-0" value="fluid gallery example image" placeholder="Alt tag">
      </div>
      <div class="form-group">
        <label for="order-0">Order:</label>
        <input type="number" name="data[images][0][order]" class="form-control image-order" id="order-0" value="0">
      </div>
      <button type="button" class="btn btn-danger remove-gallery-image-btn">× Delete</button>
    </div>
  </li>
  <li class="col-xs-12 col-sm-6 col-md-4 col-lg-3 gallery-image ui-sortable-handle">
    <div>
      <img src="http://localhost:8000/img/example.jpg">
      <input type="hidden" name="data[images][1][src]" value="img/example.jpg">
      <div class="form-group">
        <label for="title-1">Title:</label>
        <input type="text" name="data[images][1][title]" class="form-control" id="title-1" value="Default Example Image 2" placeholder="Title">
      </div>
      <div class="form-group">
        <label for="description-1">Description:</label>
        <input type="text" name="data[images][1][description]" class="form-control" id="description-1" value="A default example image." placeholder="Description">
      </div>
      <div class="form-group">
        <label for="alt-1">Alt tag (SEO):</label>
        <input type="text" name="data[images][1][alt]" class="form-control" id="alt-1" value="fluid gallery example image" placeholder="Alt tag">
      </div>
      <div class="form-group">
        <label for="order-1">Order:</label>
        <input type="number" name="data[images][1][order]" class="form-control image-order" id="order-1" value="1">
      </div>
      <button type="button" class="btn btn-danger remove-gallery-image-btn">× Delete</button>
    </div>
  </li>
  <li class="col-xs-12 col-sm-6 col-md-4 col-lg-3 gallery-image ui-sortable-handle">
    <div>
      <img src="http://localhost:8000/uploads/galleries\21\4-tux-30.jpg">
      <input type="hidden" name="data[images][2][src]" value="uploads/galleries\21\4-tux-30.jpg">
      <div class="form-group">
        <label for="title-2">Title:</label>
        <input type="text" name="data[images][2][title]" class="form-control" id="title-2" value="" placeholder="Title">
      </div>
      <div class="form-group">
        <label for="description-2">Description:</label>
        <input type="text" name="data[images][2][description]" class="form-control" id="description-2" value="" placeholder="Description">
      </div>
      <div class="form-group">
        <label for="alt-2">Alt tag (SEO):</label>
        <input type="text" name="data[images][2][alt]" class="form-control" id="alt-2" value="" placeholder="Alt tag">
      </div>
      <div class="form-group">
        <label for="order-2">Order:</label>
        <input type="number" name="data[images][2][order]" class="form-control image-order" id="order-2" value="2">
      </div>
      <button type="button" class="btn btn-danger remove-gallery-image-btn">× Delete</button>
    </div>
  </li>
  <li class="col-xs-12 col-sm-6 col-md-4 col-lg-3 gallery-image ui-sortable-handle">
    <div>
      <img src="http://localhost:8000/uploads/galleries\21\all-free-backgrounds-simple-style-darkblue-18.jpg">
      <input type="hidden" name="data[images][3][src]" value="uploads/galleries\21\all-free-backgrounds-simple-style-darkblue-18.jpg">
      <div class="form-group">
        <label for="title-3">Title:</label>
        <input type="text" name="data[images][3][title]" class="form-control" id="title-3" value="" placeholder="Title">
      </div>
      <div class="form-group">
        <label for="description-3">Description:</label>
        <input type="text" name="data[images][3][description]" class="form-control" id="description-3" value="" placeholder="Description">
      </div>
      <div class="form-group">
        <label for="alt-3">Alt tag (SEO):</label>
        <input type="text" name="data[images][3][alt]" class="form-control" id="alt-3" value="" placeholder="Alt tag">
      </div>
      <div class="form-group">
        <label for="order-3">Order:</label>
        <input type="number" name="data[images][3][order]" class="form-control image-order" id="order-3" value="3">
      </div>
      <button type="button" class="btn btn-danger remove-gallery-image-btn">× Delete</button>
    </div>
  </li>
</ul>

Comments