2

I'm creating a simple control panel for my clients webstore, and I need to store a products color options in the same row as the product in my table.

I've these two input fields:

<input class="form-control" name="color[]" placeholder="Color">
<input class="form-control" name="price[]" type="text" placeholder="0.00">

And I want to create a JSON string similar to this, so I can store it in a database and use it later on:

{"colors":{"Red":"0.00"}}

However, here's the twist:

My client can duplicate these two input fields as many times as he possibly wants, and I should generate the json from it.

 $("input[name='color[]'],input[name='price[]']").serializeArray(); 

just gives me:

[Object Object]

so I must be doing something wrong.

12
  • Expand on that object -- is it populated? Commented Oct 31, 2013 at 19:46
  • [Object Object] is the string representation of an object. .serializeArray() returns an array of objects. Commented Oct 31, 2013 at 19:48
  • @tymeJV How do I expand from it? $.jsonPARSE() isn't really helping. Commented Oct 31, 2013 at 19:48
  • expand upon it by logging it to your console so you can see what the object contains. Commented Oct 31, 2013 at 19:49
  • @KevinB I got Uncaught SyntaxError: Unexpected token o. Commented Oct 31, 2013 at 19:53

3 Answers 3

1

Serialize the form:

console.log(JSON.stringify($("form").serializeArray()));

Or you can keep your current logic and just stringify that:

console.log(JSON.stringify($("input[name='color[]'],input[name='price[]']").serializeArray()));

For example, this fiddle:

http://jsfiddle.net/8U3hw/3/

Sign up to request clarification or add additional context in comments.

1 Comment

Got this after a while of trying and fixing: [{"name":"color[]","value":"Red"},{"name":"price[]","value":"5.00"}]
0

Basic Solution - Demo

Keep your jQuery selector how you have it:

$("input[name='color[]'],input[name='price[]']").serializeArray();

The results are objects, but that is ok! If you serialize the results you will see what you've got. The result isn't going to be 100% like you want it. As you can see, all the inputs are there, but there isn't a really reliable way to know which price goes with which color.

[{"name":"color[]","value":"red"},
 {"name":"price[]","value":"3.00"},
 {"name":"color[]","value":"blue"},
 {"name":"price[]","value":"2.00"}] 

Create groupings - Demo

If you edit your named arrays to have a grouping number, then you'll be able to know which values belong together. For example, if you had two groupings, the input names would look like this:

<!-- Group 1 -->
<input class="form-control" name="color[0]" placeholder="Color">
<input class="form-control" name="price[0]" type="text" placeholder="0.00">

<!-- Group 2 -->
<input class="form-control" name="color[1]" placeholder="Color">
<input class="form-control" name="price[1]" type="text" placeholder="0.00">

Now, we have an easy way to determine which colors go with which price, but we need to update our selector a bit to account for having a number in the array:

$("input[name^='color[',input[name^='price[']").serializeArray();

Now we know our color-to-price groupings:

[{"name":"color[0]","value":"red"},
 {"name":"price[0]","value":"3.00"},
 {"name":"color[1]","value":"blue"},
 {"name":"price[1]","value":"2.00"}] 

Maintain groupings - Demo

New inputs are added programmatically, we have to maintain groups for the new inputs. Simply count the current number of color inputs and use it as the new value (since our list is zero-based).

$('#addColor').click(function(){
    var numColors = $("input[name^='color[']").length;
    var colorInput = '<input class="form-control" name="color[' + numColors + ']" placeholder="Color" />';
    var priceInput = '<input class="form-control" name="price[' + numColors + ']" placeholder="0.00" />';
    $("#colors").append(colorInput);
    $("#colors").append(priceInput);
});

this creates new inputs using the correct group numbers:

<input class="form-control" name="color[3]" placeholder="Color">
<input class="form-control" name="price[3]" placeholder="0.00">

Massage results into desired output - Final Demo & Answer

First, it is easier to go ahead and split up the colors and prices into 2 different arrays. We'll use the group number to figure out which price goes with which color:

var colors = $("input[name^='color[']").serializeArray();
var prices = $("input[name^='price[']").serializeArray();

Loop through the colors. For each color, get its grouping number. To do this, we'll use regex on the name attribute. Then, using that grouping number, find the matching price. To do that, we have to loop through the prices. This isn't as slow as it sounds, most likely it is going to be the very first price we check, because the inputs are in order. But I don't believe order is guaranteed by serializeArray, so we loop just in case. When we find the matching price, save its value, then remove it from the prices array, queuing up the next price we'll need for the next color.

var finalResults = {};
var colors = $("input[name^='color[']").serializeArray();
var prices = $("input[name^='price[']").serializeArray();

var rowPattern = /\[(\d+)\]$/; // Gets the group number inside []
var groupNum = 0;

// For each color, we have to find its matching price
$(colors).each( function(index, input){
    var groupNum = rowPattern.exec(input.name)[1];
    var myPrice = null;

    for(var i=0; i < prices.length; i++){
        if(prices[i].name = "price[" + groupNum + "]"){
            myPrice = prices[i].value;
            // remove price from list for faster future lookups
            prices.splice(i,1);
            break;
        }
    }

    finalResults[input.value] = myPrice;
});

finalResults = {"Colors": finalResults};  
console.log(JSON.stringify(finalResults));

1 Comment

Whoa, you really used some time on this one! +1000
0

You need to use .serializeArray() on the parent <form> element, not the input fields! But serializeArray might not return the result in the format you would expect. Here is a function that does this the way you want it to. Pass it the jQuery reference for your <from> like: createColorJSON($('#myForm')).

function createColorJSON($form){
    var colors = $form.find("input[name='color[]']"),
        prices = $form.find("input[name='price[]']"),
        object = {colors:{}};

    if (colors.length !== prices.length) throw new Error('Form element number mismatch');

    for (var i = 0; i < ilength; i++){
        var color = colors.eq(i).val(),
            price = prices.eq(i).val();
        object.colors[color] = price;
    }

    return object;
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.