Populate array with foreach in foreach javascript (angular)
I have categories. and each category has elements. now i am returning category list and item list from api.
now in angular i want to do this into 1 object. I did the following:
if ($scope.categories_norm) {
$scope.delivery_items = [];
//get categories
angular.forEach(data.item_categories.normal_categories, function (v, k) {
//push categories
$scope.delivery_items.push(v);
//push items for categories
var i = 0;
if ($scope.items) {
angular.forEach($scope.items, function (val, key) {
i++;
if (val.item_category_id == v.item_category_id) {
//console.log();
$scope.delivery_items[k][i].push(val);
}
});
}
});
}
for some reason i can't fill it. it returns errors: TypeError: Cannot read property "push" of undefined
how should i do this properly? I want an object inside each category object with all elements
source to share
I think the problem is k
to $scope.delivery_items[k][i].push(val);
change it on v
and see what happens.
EDIT:
Ok, after looking at your question again, I thought this might work better:
if ($scope.categories_norm) {
$scope.delivery_items = {}; // create empty object
//get categories
angular.forEach(data.item_categories.normal_categories, function (v, k) {
var catagery = v.category_name; // create cataogry variable scoped to this block
$scope.delivery_items[category] = {}; //create empty category object using category name as the key
if ($scope.items) {
angular.forEach($scope.items.filter(check_item_category(v.item_category_id)), function (val, key) {
$scope.delivery_items[category][category_info] = v; // comment out or omit this line if you don't want category information included within the category
$scope.delivery_items[category][val.item_name] = val; // set item object to it corosponding name
});
};
});
}
function check_item_category (category_id) {
return function(item) {
return item.item_category_id == category_id
}
}
You still have to fill in a bit (namely how to get the category and item names), but that should be what you want.
EDIT: I switched to using a filter, I just didn't like seeing the ID check for each item, I think using a filter would just be cleaner.
EDIT:
As a result, it should have an object like this:
{
"category_1" : {
"category_info" : category_object,
"item_1" : item_1_object,
"item_2" : item_2_object
}
"category_2" : {
"category_info" : category_object,
"item_1" : item_1_object,
"item_2" : item_2_object,
"item_3" : item_3_object,
}
"category_3" : {
"category_info" : category_object,
"item_1" : item_1_object,
"item_2" : item_2_object,
"item_3" : item_3_object,
}
}
EDIT: Ok, the last time I looked at this again and realized that it could be done faster (reduction in time $scope.items
is done by iteration) and at the same time remove duplicate data (item name is in both key and object object).
Please note that you will not be storing the category object along with the category if you use this solution
if ($scope.categories_norm) {
$scope.delivery_items = get_items_sorted_by_category(data.item_categories.normal_categories,$scope.items) // create empty object
});
}
function get_items_sorted_by_category(categories,items) {
var filled_object = {}
for(var category in categories){
//will need to change how you set the catagory name as I don't know how this object looks
filled_object[category.name] = items.filter(check_item_category(category.item_category_id)) // will filter out any objects that don't have the correct caragory ID
};
return filled_object;
}
function check_item_category (category_id) {
return function(item) {
return item.item_category_id == category_id
}
}
you should get an object that looks like this:
{
"category_1" : [
"item_1",
"item_2",
"item_3"
]
"category_2" : [
"item_1",
"item_2",
"item_3"
]
"category_3" : [
"item_1",
"item_2",
"item_3"
]
}
source to share
Remove '[i]'
if ($scope.categories_norm) {
$scope.delivery_items = [];
//get categories
angular.forEach(data.item_categories.normal_categories, function (v, k) {
//push categories
$scope.delivery_items.push(v);
//push items for categories
var i = 0;
if ($scope.items) {
angular.forEach($scope.items, function (val, key) {
i++;
if (val.item_category_id == v.item_category_id) {
//console.log();
$scope.delivery_items[k].push(val);
}
});
}
});
}
Or remove 'push':
if ($scope.categories_norm) {
$scope.delivery_items = [];
//get categories
angular.forEach(data.item_categories.normal_categories, function (v, k) {
//push categories
$scope.delivery_items.push(v);
//push items for categories
var i = 0;
if ($scope.items) {
angular.forEach($scope.items, function (val, key) {
i++;
if (val.item_category_id == v.item_category_id) {
//console.log();
$scope.delivery_items[k][i] = val;
}
});
}
});
}
source to share