1

I know there are a lot of questions about this, but I can't find the solution to my problem and have been on it for a while now. I have two sets of input fields with the same name, one for product codes, and one for product names. These input fields can be taken away and added to the DOM by the user so there can be multiple:

Here is what I have so far, although this saves it so there all the codes are in one array, and all the names in another:

var updatedContent = [];
var varCode = {};
var varName = {};

$('.productVariationWrap.edit input[name="varVariationCode[]"]')
   .each(function(i, vali){
     varCode[i] = $(this).val();
   });

$('.productVariationWrap.edit input[name="varVariationName[]"]')
  .each(function(i1, vali1){
    varName[i1] = $(this).val();
  });

updatedContent.push(varCode);
updatedContent.push(varName);

I am trying to get it so the name and code go into the same array. i.e. the code is the key of the K = V pair?

Basically so I can loop through a final array and have the code and associated name easily accessible.

I can do this in PHP quite easily but no luck in javascript.

EDIT

I want the array to look like:

[
    [code1, name1],
    [code2, name2],
    [code3, name3]
];

So after I can do a loop and for each of the arrays inside the master array, I can do something with the key (code1 for example) and the associated value (name1 for example). Does this make sense? Its kind of like a multi-dimensional array, although some people may argue against the validity of that statement when it comes to Javascript.

ErikE
  • 48,881
  • 23
  • 151
  • 196
JamesG
  • 2,018
  • 2
  • 28
  • 57

3 Answers3

3

I think it's better for you to create an object that way you can access the key/value pairs later without having to loop if you don't want to:

var $codes = $('.productVariationWrap.edit input[name="varVariationCode[]"]'),
    $names = $('.productVariationWrap.edit input[name="varVariationName[]"]'),
    updatedContent = {};

for (var i = 0, il = $codes.length; i < il; i++) {
    updatedContent[$codes.get(i).value] = $names.get(i).value;
}

Now for example, updatedContent.code1 == name1, and you can loop through the object if you want:

for (var k in updatedContent) {
    // k == code
    // updatedContent[k] == name
}
mVChr
  • 49,587
  • 11
  • 107
  • 104
1

Using two loops is probably not optimal. It would be better to use a single loop that collected all the items, whether code or name, and then assembled them together.

Another issue: your selectors look a little funny to me. You said that there can be multiple of these controls in the page, but it is not correct for controls to have duplicate names unless they are mutually exclusive radio buttons/checkboxes--unless each pair of inputs is inside its own ancestor <form>? More detail on this would help me provide a better answer.

And a note: in your code you instantiated the varCode and varName variables as objects {}, but then use them like arrays []. Is that what you intended? When I first answered you, i was distracted by the "final output should look like this array" and missed that you wanted key = value pairs in an object. If you really meant what you said about the final result being nested arrays, then, the smallest modification you could make to your code to make it work as is would look like this:

var updatedContent = [];

$('.productVariationWrap.edit input[name="varVariationCode[]"]')
   .each(function(i, vali){
      updatedContent[i] = [$(this).val()]; //make it an array
   });

$('.productVariationWrap.edit input[name="varVariationName[]"]')
   .each(function(i1, vali1){
      updatedContent[i1].push($(this).val()); //push 2nd value into the array
   });

But since you wanted your Code to be unique indexes into the Name values, then we need to use an object instead of an array, with the Code the key the the Name the value:

var updatedContent = {},
   w = $('.productVariationWrap.edit'),
   codes = w.find('input[name="varVariationCode[]"]'),
   names = w.find('input[name="varVariationName[]"]');

for (var i = codes.length - 1; i >= 0; i -= 1) {
   updatedContent[codes.get(i).val()] = names.get(i).val();
});

And please note that this will produce an object, and the notation will look like this:

{
    'code1': 'name1',
    'code2': 'name2',
    'code3': 'name3'
};

Now you can use the updatedContent object like so:

var code;
for (code in updatedContent) {
    console.log(code, updatedContent[code]); //each code and name pair
}

Last of all, it seems a little brittle to rely on the Code and Name inputs to be returned in the separate jQuery objects in the same order. Some way to be sure you are correlating the right Code with the right Name seems important to me--even if the way you're doing it now works correctly, who's to say a future revision to the page layout wouldn't break something? I simply prefer explicit correlation instead of relying on page element order, but you may not feel the need for such surety.

ErikE
  • 48,881
  • 23
  • 151
  • 196
  • @JamesG there is looping through DOM nodes twice, which you absolutely don't need to do. See my answer. – vittore Mar 18 '13 at 22:53
0

I don't like the way to solve it with two loops

 var updatedContent = [] 

 $('.productVariationWrap.edit').each(function(i, vali){
     var $this = $(this)
     , tuple = [$this.find('input[name="varVariationCode[]"]').val()
                , $this.find('input[name="varVariationName[]"]').val()]

     updatedContent.push(tuple)
 });
vittore
  • 17,449
  • 6
  • 44
  • 82