0

I need to create a javascript (jquery) array with duplicated key name like next one

{
    "apple": "type1",
    "apple": "type2",
}

Here is my current code I stack with

var data = {};
jQuery.each(formData, function(i, field) {
    data[field.name] = field.value;
});

In above example field.name is "apple" have different values like "type1" or "type2".

With my current code when same field.name in jQuery.each I got removed/erased "apple":"type1"

Ammar
  • 770
  • 4
  • 11
S.M. Pat
  • 308
  • 3
  • 12
  • 5
    Object keys are unique, one key cannot store two values. Use an array, or an array of objects for this matter. – Kobe Jun 17 '19 at 08:05
  • 5
    why not do it like { "apple" : ['type1' , 'type2'] } – Kevin.a Jun 17 '19 at 08:07
  • It's an expected behavior since object keys are unique, If you want to have different values for the same key, you can use an array as a value – Ammar Jun 17 '19 at 08:07
  • Possible duplicate of [JS associative object with duplicate names](https://stackoverflow.com/questions/3996135/js-associative-object-with-duplicate-names) – Charlie Jun 17 '19 at 08:16
  • @Kevin.a because I have limitations by software, I can't rebuild it to use correct array structure. – S.M. Pat Jun 17 '19 at 09:17

1 Answers1

1

This is not a jQuery problem, but rather it is to do with the nature of objects in javascript. You can't store multiple values on the same key (how would you access them?).

What you can do is store an array on a key, and add to that:

const formData = jQuery('input');
let data = {};

jQuery('button').click(function() {
  data = {}
  jQuery.each(formData, function(i, field) {
    data[field.name] = data.hasOwnProperty(field.name)
      ? [...data[field.name], field.value]
      : [field.value]
  });
  
  console.dir(data);
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input name="a" />
<input name="b" />
<input name="b" />
<button>Test</button>

What the above code does is use an array against a key, and add to that array for each item.

You can do this without jQuery, and without an each, you may or may not prefer this option:

const button = document.querySelector('button');
const getAll = selector => Array.prototype.slice.call(
  document.querySelectorAll(selector)
);

let data = {};

button.onclick = () => {
  data = getAll('input')
    .reduce((result, element) => ({
      ...result,
      [element.name]: result.hasOwnProperty(element.name)
        ? [...result[element.name], element.value]
        : [element.value]
    }), {})
    
  console.dir(data)
}
<input name="a" />
<input name="b" />
<input name="b" />
<button>Test</button>
OliverRadini
  • 6,238
  • 1
  • 21
  • 46
  • 1
    This breaks on multiple clicks, but I get the gist of it. Moving the object declaration inside the button click will fix this – Kobe Jun 17 '19 at 08:15
  • @Kobe very true, good spot, thanks for that. Answer updated now – OliverRadini Jun 17 '19 at 08:16
  • 1
    you are right but I was limited by software form which incorrectly allow to have inputs with same id/name but different values. Anyway your answer help me. – S.M. Pat Jun 17 '19 at 08:35
  • what three ```...``` mean in the ```[...data[field.name]```? – S.M. Pat Jun 17 '19 at 09:23
  • 1
    This is the [spread syntax](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax). It 'spreads' out the existing contents of that array into a new array. – OliverRadini Jun 17 '19 at 09:38