Reputation: 1590
I need to map an array of inputs to pass via an ajax call. Inputs look like this:
<input type="hidden" name="sizes[0][id]" value="0" class="sizes">
<input type="hidden" name="sizes[0][name]" value="Small" class="sizes">
<input type="hidden" name="sizes[1][id]" value="1" class="sizes">
<input type="hidden" name="sizes[1][name]" value="Medium" class="sizes">
<input type="hidden" name="sizes[2][id]" value="2" class="sizes">
<input type="hidden" name="sizes[2][name]" value="Large" class="sizes">
I'm trying to map it like the following, but it is not working as it doesn't grab the id or name field.
var sizes = $('input.sizes').map(function(){ return $(this).val(); }).get();
Maybe this needs to be recursive somehow?
Edit: The output needs to work with the following code:
$.ajax({
type : "POST",
cache : false,
data : {
sizes: sizes,
...
},
url : 'http://what.does.the.fox/say',
dataType : 'json',
...
});
Another update: This should create an array of objects that resemble the input name tag. ie:
var sizes = [
{ id: 0, name: 'Small' },
{ id: 1, name: 'Medium' },
{ id: 2, name: 'Large' }
];
Upvotes: 1
Views: 729
Reputation: 1590
I found code online that is able to do this as I want it. This also makes it completely dynamic so it doesn't matter what fields are named, or how many there are. Here is the code I found here in a comment:
(function(jQuery){
jQuery.fn.MytoJson = function(options) {
options = jQuery.extend({}, options);
var self = this,
json = {},
push_counters = {},
patterns = {
"validate": /^[a-zA-Z][a-zA-Z0-9_]*(?:\[(?:\d*|[a-zA-Z0-9_]+)\])*$/,
"key": /[a-zA-Z0-9_]+|(?=\[\])/g,
"push": /^$/,
"fixed": /^\d+$/,
"named": /^[a-zA-Z0-9_]+$/
};
this.build = function(base, key, value){
base[key] = value;
return base;
};
this.push_counter = function(key){
if(push_counters[key] === undefined){
push_counters[key] = 0;
}
return push_counters[key]++;
};
jQuery.each(jQuery(this).serializeArray(), function(){
// skip invalid keys
if(!patterns.validate.test(this.name)){
return;
}
var k,
keys = this.name.match(patterns.key),
merge = this.value,
reverse_key = this.name;
while((k = keys.pop()) !== undefined){
// adjust reverse_key
reverse_key = reverse_key.replace(new RegExp("\\[" + k + "\\]$"), '');
// push
if(k.match(patterns.push)){
merge = self.build([], self.push_counter(reverse_key), merge);
}
// fixed
else if(k.match(patterns.fixed)){
merge = self.build([], k, merge);
}
// named
else if(k.match(patterns.named)){
merge = self.build({}, k, merge);
}
}
json = jQuery.extend(true, json, merge);
});
return json;
}
})(jQuery);
Upvotes: 1
Reputation: 34416
EDITED: This is what you want - http://jsfiddle.net/jayblanchard/2F5vD/3/ (Now new and improved with proper quotes!)
var dataString = '';
dataString += '[';
var inputLength = $('input.sizes').length;
$('input.sizes').each(function(index) {
if( $(this).is('[name$="[id]"]') ) {
dataString += '\'' + $(this).val() + '\':';
dataString += '{ id:' + $(this).val() + ',';
} else if( $(this).is('[name$="[name]"]') && 0 != inputLength -1 ) {
dataString += ' name:\'' + $(this).val() + '\'},';
} else {
dataString += ' name:\'' + $(this).val() + '\'}';
}
inputLength--;
});
dataString += ']';
It produces the following output (that will now pass JSLint)-
[{"0":{ "id":"0", "name":"Small"},"1":{ "id":"1", "name":"Medium"},"2":{ "id":"2", "name":"Large"}}]
This pretty much used brute force methodology to get a JSON string and there may be some much easier ways to do this. this can easily be ported to a function that can be called over and over. I hope that it helps.
Upvotes: 0
Reputation: 30015
var sizes = $('input.sizes').map(function(){
return { id : this.id,
name : this.name,
val : $(this).val()
};
}).get();
Note for jQuery-o-philes: in this case this.id
is the same as $(this).attr('id')
, its just that we don't need jQuery to get the id if we already have the element. Same thing with this.name
.
Upvotes: 0