2011-12-20 207 views
11

Estoy un poco perdido. Estoy consiguiendo este JSON:GroupBy en JavaScript para agrupar datos JSON y poblar en optgroup

[{ 
    "id": "210", 
    "name": "Name 1", 
    "category": "Category 1" 
}, { 
    "id": "187", 
    "name": "Name 2", 
    "category": "Category 1" 
}, { 
    "id": "186", 
    "name": "Name 3", 
    "category": "Category 1" 
}, { 
    "id": "185", 
    "name": "Name 4", 
    "category": "Category 1" 
}, { 
    "id": "184", 
    "name": "Name 5", 
    "category": "Category 1" 
}, { 
    "id": "183", 
    "name": "Name 6", 
    "category": "Category 1" 
}, { 
    "id": "182", 
    "name": "Name 7", 
    "category": "Category 1" 
}, { 
    "id": "181", 
    "name": "Name 8", 
    "category": "Category 2" 
}, { 
    "id": "180", 
    "name": "Name 9", 
    "category": "Category 3" 
}, { 
    "id": "178", 
    "name": "Name 10", 
    "category": "Category 2" 
}] 

Y me gustaría poner todo esto en un selecto con opciones y optgroups. En realidad, el optgroup debe ser categoría

me gustaría algo como esto:

<select name="products" class="product" id="product"> 
<optgroup label="Category 1"> 
    <option value="210">Name 1</option> 
    <option value="187">Name 2</option> 
    <option value="186">Name 3</option> 
    <option value="185">Name 4</option> 
    ... 
</optgroup> 
<optgroup label="Category 2"> 
    <option value="181">Name 8</option> 
    <option value="178">Name 10</option> 
</optgroup> 
<optgroup label="Category 3"> 
    <option value="180">Name 9</option> 
</optgroup> 

Hoy sólo he hecho esto porque estoy luchando demasiado:

$(document).ready(function() { 
    $.getJSON("5.php", { 
     val: $(this).val() 
    }, function (data) { 
     $.each(data, function (i, item) { 
      $("<option/>").attr("value", item.id).append(item.name).appendTo("optgroup"); 
     }); 
    }); 
}); 

Como no puede ver ningún grupo de opciones :) ¿Hay alguna manera de hacerlo? También puedo modificar mi JSON si puede hacerlo más fácil.

Gracias por cualquier ayuda.

Respuesta

16

Suponiendo que ya existen las optgroups, cambiar esta ...

.appendTo("optgroup") 

a este ...

.appendTo("optgroup[label='" + item.category + "']"); 

http://jsfiddle.net/FG9Lg/


Si no existen, se necesito crearlos, aunque sugeriría una reestructuración de su respuesta JSON para tener cada elemento anidado debajo del categoría adecuada

Así ...

{ 
    "Category 1":[ 
     {"id": "210","name": "Name 1"}, 
     {"id": "187","name": "Name 2"}, 
     {"id": "186","name": "Name 3"}, 
     {"id": "185","name": "Name 4"}, 
     {"id": "184","name": "Name 5"}, 
     {"id": "183","name": "Name 6"}, 
     {"id": "182","name": "Name 7"} 
    ], 
    "Category 2":[ 
     {"id": "181","name": "Name 8"}, 
     {"id": "178","name": "Name 10"} 
    ], 
    "Category 3": [ 
     {"id": "180","name": "Name 9"} 
    ] 
} 

Así que entonces podría hacer esto:

var product = $('#product'); 

$.each(data, function (key, cat) { 
    var group = $('<optgroup>',{label:key}); 

    $.each(cat,function(i,item) { 
     $("<option/>",{value:item.id,text:item.name}) 
      .appendTo(group); 
    }); 

    group.appendTo(product); 
}); 

http://jsfiddle.net/FG9Lg/1/

+1

nombre de usuario EPIC es todo lo que tengo que decir. – donutdan4114

+0

@ donutdan4114 Gracias. Era eso o "¡MÍRAME! ¡MÍRAME!". –

+1

muchas gracias! ¡He modificado mi JSON y he hecho lo que dijiste! ¡Funciona perfectamente! – user1108276

16

Si yo fuera usted, me gustaría utilizar una pequeña biblioteca llamada Underscore para agrupar los datos que se devuelven en una representación más fácil.

ver este código de abajo y también se pueden ver esto live demo:

var groupData = _.groupBy(data, function (obj) { 
    return obj.category; 
}); 

var optGroups = []; 
for (var key in groupData) { 
    if (groupData.hasOwnProperty(key)) { 
     var optGroup = $("<optgroup></optgroup>"); 
     optGroup.attr("label", key); 
     var currentGroup = groupData[key]; 
     for (var i = 0; i < currentGroup.length; i++) { 
      $("<option />").attr("value", currentGroup[i].id).html(currentGroup[i].name).appendTo(optGroup); 
     } 
     optGroups.push(optGroup); 
    } 
} 

for(var i = 0; i < optGroups.length; i++) { 
    $("#products").append(optGroups[i]); 
} 

Si dudan en utilizar la biblioteca de subrayado, se podrá considerar la presente groupBy función:

var groupBy = function(array, predicate) { 
    var grouped = {}; 
    for(var i = 0; i < array.length; i++) { 
     var groupKey = predicate(array[i]); 
     if (typeof(grouped[groupKey]) === "undefined") 
      grouped[groupKey] = []; 
     grouped[groupKey].push(array[i]); 
    } 

    return grouped; 
} 

USO:

var groupData = groupBy(data, function (obj) { 
    return obj.category; 
}); 
0

En caso de que quiera para mantenerlo formato JSON como es, lo siguiente sería responder a su pregunta:

//Loop through the json, get distinct category names, and append them as optgroup to the select dropdown 
var categories = []; 
$.each(data, function(index, item) { 
    if ($.inArray(item.category, categories) == -1) { 
     categories.push(item.category); 
     var optgroupId = "cat-" + item.category.replace(/\s/g, ""); 
     $('#id_of_select_dropdown').append('<optgroup id ="'+optgroupId+'"label="'+item.category+'">'); 
    } 
}); 
// append the options to their corresponding optgroups 
$.each(data.response, function(index, item) { 
    var optgroupId = "cat-" + item.category.replace(/\s/g, ""); 
    $('#'+optgroupId).append('<option>' + item.name + '</option>'); 
}); 

Espero que esto ayude!

2

Sé que este hilo es muy antiguo, pero necesitaba algo similar y se me ocurrió esto. Agrega automáticamente grupos de opción cuando es necesario y los llena con opciones. Además, funciona tanto cuando tiene grupos optgroups como cuando no.

http://jsfiddle.net/mzj0nuet/

var select = $('#product'); 

$.each(data, function (key, cat) { 
    var option = "<option value='"+cat.id+"'>"+cat.name+"</option>"; 

    // If we ave a category property, add this item to an optgroup 
    if (cat.hasOwnProperty("category")) { 
     var group = cat.category; 

     // If this optgroup is not already present, add it 
     if (select.find("optgroup[label='" + group + "']").length === 0) { 
      select.append("<optgroup label='" + group + "' />"); 
     } 

     select.find("optgroup[label='" + group + "']").append(option); 

    // No category, no optgroup. Add this as simple option 
    } else { 
     select.append(option); 
    }   
});