GroupBy в JavaScript для группировки данных JSON и заполнения в optgroup
Я немного потерял. Я получаю этот JSON:
[{
"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"
}]
и я хотел бы поместить все это в select с options и optgroups. На самом деле optgroup должна быть категорией
Я хотел бы что-то вроде этого:
<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>
сегодня я сделал это только потому, что я борюсь слишком много:
$(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");
});
});
});
Как видите не optgroup :) Есть ли способ сделать это? Я также могу изменить свой JSON, если он может это сделать облегчающий.
Спасибо за любую помощь.
4 ответов
предполагая, что группы optgroups уже существуют, измените это...
.appendTo("optgroup")
для этого...
.appendTo("optgroup[label='" + item.category + "']");
если они не существуют, вам нужно их создать, хотя я бы предложил реструктуризацию вашего ответа JSON, чтобы каждый элемент был вложен в соответствующую категорию.
такой...
{
"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"}
]
}
так что вы могли бы сделать это:
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 );
});
на вашем месте я бы использовал небольшую библиотеку под названием подчеркивание сгруппировать данные, которые возвращаются в более простом представлении.
посмотреть этот код ниже, и вы также можете увидеть это 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]);
}
если вы не решаетесь использовать библиотеку подчеркивания, вы можете рассмотреть это :
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;
}
использование:
var groupData = groupBy(data, function (obj) {
return obj.category;
});
Я знаю, что эта нить очень старая, но мне нужно было что-то подобное, и я придумал это. Он автоматически добавляет optgroups, когда это необходимо, и заполняет их опциями. Кроме того, он работает как при наличии optgroups, так и при отсутствии.
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);
}
});
Если вы хотите сохранить формат JSON как есть, на ваш вопрос ответит следующее:
//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>');
});
надеюсь, что это помогает!