AngularJS ng-repeat for object contains objects and arrays - angularjs

I have an object, which has objects inside, and arrays in child objects. Here's the structure:
var keywords = {
"Animals" : {
"Pets" : [
"Guppy", "Parrot", "Goldfish", "Dog", "Cat"
],
"Wild animals" : [
"Tiger", "Ant", "Tetra", "Peafowl", "Mongoose"
],
"Domestic animals" : [
"Cow", "Pig", "Goat", "Horse"
]
},
"Food" : {
"Fast food" : [
"Cheeseburger", "Hamburger"
],
"Dessert" : [
"Chocolate", "Cookie", "Cake", "Pie"
]
},
"Vehicle" : {
"Motorcycle" : [
"Harley Davidson"
],
"Car" : [
"Lamborghini", "Ferrari", "Bugatti", "BMW", "Mercedes"
]
},
"Movie" : {
"Science fiction" : [
"Sunshine", "Interstellar", "The Moon", "Oblivion", "Star Trek", "Star Wars"
]
}
};
I've made a foreach loop for looping through the elements inside and print them on screen:
angular.forEach(keywords, function(value, key) {
console.log(key);
angular.forEach(value, function(value, key) {
console.log(key);
angular.forEach(value, function(value, key) {
console.log(value);
})
})
})
Now, I'm trying to do the same with ng-repeat directive on a div (that has a div in it, and another in the child div), but can't make it work, have no clue how to start it. Any idea?

var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope) {
$scope.keywords = {
"Animals": {
"Pets": [
"Guppy", "Parrot", "Goldfish", "Dog", "Cat"
],
"Wild animals": [
"Tiger", "Ant", "Tetra", "Peafowl", "Mongoose"
],
"Domestic animals": [
"Cow", "Pig", "Goat", "Horse"
]
},
"Food": {
"Fast food": [
"Cheeseburger", "Hamburger"
],
"Dessert": [
"Chocolate", "Cookie", "Cake", "Pie"
]
},
"Vehicle": {
"Motorcycle": [
"Harley Davidson"
],
"Car": [
"Lamborghini", "Ferrari", "Bugatti", "BMW", "Mercedes"
]
},
"Movie": {
"Science fiction": [
"Sunshine", "Interstellar", "The Moon", "Oblivion", "Star Trek", "Star Wars"
]
}
};
});
.section1{
background-color: CornflowerBlue;
}
.section2{
background-color: lightblue;
}
.section3{
background-color: Azure ;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<body ng-app="myApp" ng-controller="myCtrl">
<div ng-repeat="(keyword, list) in keywords" class="section1">
{{keyword}}
<div ng-repeat="(name, items) in list" class="section2">
{{name}}
<div ng-repeat="item in items" class="section3">
{{item}}
</div>
</div>
</div>
</body>

I think we are not using ng-repeat with this type of array.
You should go throw with this logic.
$scope.html ="";
angular.forEach(keywords, function(value, key) {
$scope.html += "<div>"+ key ;
angular.forEach(value, function(value, key) {
$scope.html += "<div>"+ key ;
angular.forEach(value, function(value, key) {
$scope.html += "<div>"+ key + "</div>";
})
$scope.html += "</div>";
})
$scope.html += "</div>";
})
and Print 'html' scope into your HTML page.
{{html}}
I know this is not perfect solution but it's trick to fix you current problem.

Related

angular js, javascript, jquery, bootstrap [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 5 years ago.
Improve this question
Please let me know how to display the metrics, name, and nodes of the cluster using ng-repeat in a div.
Following is the JSON:-
[
{
"metrics":{
"groupMetric_2":"value2",
"groupMetric_1":"value1",
"groupMetric_0":"value0"
},
"name":"myGroup",
"clusters":[
{
"metrics":{
"cluster1_1":"value1",
"cluster1_0":"value0",
"cluster1_3":"value3",
"cluster1_2":"value2",
"cluster1_4":"value4"
},
"name":"cluster1",
"nodes":[
{
"metrics":{
"cluster1_node_1_0":"value0",
"cluster1_node_1_2":"value2",
"cluster1_node_1_1":"value1",
"cluster1_node_1_4":"value4",
"cluster1_node_1_3":"value3"
},
"name":"cluster1_node_1"
},
{
"metrics":{
"cluster1_node_2_1":"value1",
"cluster1_node_2_0":"value0",
"cluster1_node_2_3":"value3",
"cluster1_node_2_2":"value2",
"cluster1_node_2_4":"value4"
},
"name":"cluster1_node_2"
},
{
"metrics":{
"cluster1_node_3_0":"value0",
"cluster1_node_3_2":"value2",
"cluster1_node_3_1":"value1",
"cluster1_node_3_4":"value4",
"cluster1_node_3_3":"value3"
},
"name":"cluster1_node_3"
}
]
},
{
"metrics":{
"cluster2_0":"value0",
"cluster2_2":"value2",
"cluster2_1":"value1",
"cluster2_4":"value4",
"cluster2_3":"value3"
},
"name":"cluster2",
"nodes":[
{
"metrics":{
"cluster2_node_1_4":"value4",
"cluster2_node_1_2":"value2",
"cluster2_node_1_3":"value3",
"cluster2_node_1_0":"value0",
"cluster2_node_1_1":"value1"
},
"name":"cluster2_node_1"
},
{
"metrics":{
"cluster2_node_3_4":"value4",
"cluster2_node_3_2":"value2",
"cluster2_node_3_3":"value3",
"cluster2_node_3_0":"value0",
"cluster2_node_3_1":"value1"
},
"name":"cluster2_node_3"
},
{
"metrics":{
"cluster2_node_2_3":"value3",
"cluster2_node_2_4":"value4",
"cluster2_node_2_1":"value1",
"cluster2_node_2_2":"value2",
"cluster2_node_2_0":"value0"
},
"name":"cluster2_node_2"
}
]
}
]
}
]
Thanks.
You need to learn 2 things to achieve it :
1) How to access elements of Array.
You can access the array values by using the index number.
Example :
var myObj, x;
myObj = {
"name":"John",
"age":30,
"cars":[ "Ford", "BMW", "Fiat" ]
};
x = myObj.cars[0];
Check it here to learn more.
2) How to access properties of Object.
You can access the object values by using dot (.) notation:
Example :
myObj = { "name":"John", "age":30, "car":null };
x = myObj.name;
Check it here to learn more.
Finally, you'll be ready to learn the usage of ng-repeat in AngularJS :
var app = angular.module("myApp", []);
app.controller("myCtrl", function($scope) {
$scope.records = [
{
"Name" : "Alfreds Futterkiste",
"Country" : "Germany"
},
{
"Name" : "Berglunds snabbköp",
"Country" : "Sweden"
},
{
"Name" : "Centro comercial Moctezuma",
"Country" : "Mexico"
},
{
"Name" : "Ernst Handel",
"Country" : "Austria"
}
]
});
<!DOCTYPE html>
<html>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.4/angular.min.js"></script>
<body ng-app="myApp">
<table ng-controller="myCtrl" border="1">
<tr ng-repeat="x in records">
<td>{{x.Name}}</td>
<td>{{x.Country}}</td>
</tr>
</table>
</body>
</html>

Consuming JSON Object in AngularJs

My Spring Rest Controller Endpoint is as below:
#CrossOrigin
#RequestMapping(value = "/getEverything", method=RequestMethod.GET)
public #ResponseBody MyItems getEverything(){
return myService.getEverything();
}
Below is MyItems class:
public class MyItems {
private Map<String, ArrayList<MyItem>> everything;
public Map<String, ArrayList<MyItem>> getEverything() {
return everything;
}
public void setEverything(Map<String, ArrayList<MyItem>> everything) {
this.everything = everything;
}
}
The rest call returns Json in below format:
{
"myItems": {
"Office": [
{
"field1": "Read a book",
"field2": "xyz",
"field3": true,
"field4": 1489795200000
},
{
"field1": "Write a program",
"field2": "abc",
"field3": false,
"field4": 1489881600000
}
],
"Home": [
{
"field1": "Watch a movie",
"field2": "pqr",
"field3": true,
"field4": 1489797800000
}
]
}
}
Here Office, Home are keys in the returned map.
How do I iterate or consume this JSon in AngularJS?
How do I get the key values ?
$http.get(REST_SERVICE_URI + 'toDo/getAllItems').then(function(response){
// what will go here ?
$scope.myItemLists = response.data;
});
I want myItemLists as a List containing objects with two properties:
1) Listname: This will be the key of the map returned.
2) List of Fields: This will be the list of object returned.
Thanks!
Try like this. use angular forEach loop
var app = angular.module('app', []);
app.controller('aCtrl', function($scope) {
$scope.myItems ={
"myItems": {
"Office": [
{
"field1": "Read a book",
"field2": "xyz",
"field3": true,
"field4": 1489795200000
},
{
"field1": "Write a program",
"field2": "abc",
"field3": false,
"field4": 1489881600000
}
],
"Home": [
{
"field1": "Watch a movie",
"field2": "pqr",
"field3": true,
"field4": 1489797800000
}
]
}
}
var keys = [];
var objectValues = [];
angular.forEach($scope.myItems.myItems,function(value,key){
keys.push(key);
objectValues.push(value);
})
console.log(keys);
console.log(objectValues);
})
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.22/angular.min.js"></script>
<div ng-app="app" ng-controller="aCtrl">
</div>
you can store data in separate variable see below,
$http.get(REST_SERVICE_URI + 'toDo/getAllItems').then(function(response){
// what will go here ?
$scope.myItemLists = response.data;
$scope.itemListOfficeData = response.data.myItems.Office;
$scope.itemListHomeData = response.data.myItems.Home;
});
Or you can use nested data-ng-repeat for iterate data see below link for reference.
Nested ng-repeat
using ng-repeat inside another ng-repeat
While HJz answer is fine if what you want is to iterate through your json data in the controller, but if you simply want to present the data in a view, you can use ng-repeat directly on your json object like this:
<ul>
<li ng-repeat="(key, value) in myItems">{{key}}: {{value | json}}</li>
<ul>
which roughly turns into the following html (some values have been ignored for better readability):
<ul>
<li>Office: [{"field1": "Read a book"}, {"field1": "Read a book"}]</li>
<li>Home: [{"field1": "Watch a movie"}]</li>
<ul>
You can nest this ng-repeat directives, to further iterate through the values in your json data.
Alternatively, if all you need is an array of keys or an array of values, then JavaScript got functions you can use to extract those:
var keys = Object.keys(myItems);
// -> ['Office', 'Home']
var values = Object.values(myItems);
// -> [[{"field1": "Read a book"}, {"field1": "Write a program"}], [{"field1": "Watch a movie"}]]
You can flatten the nested object first and then iterate over it or you can use nested ng-repeat as shown below:
var app = angular.module('app', []);
app.controller('aCtrl', function($scope) {
var items = {
"myItems": {
"Office": [{
"field1": "Read a book",
"field2": "xyz",
"field3": true,
"field4": 1489795200000
},
{
"field1": "Write a program",
"field2": "abc",
"field3": false,
"field4": 1489881600000
}
],
"Home": [{
"field1": "Watch a movie",
"field2": "pqr",
"field3": true,
"field4": 1489797800000
}]
}
}
$scope.myItems = items.myItems;
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.22/angular.min.js"></script>
<div ng-app="app" ng-controller="aCtrl">
<ul>
<li ng-repeat="(item, fields) in myItems">
{{item}}
<ul>
<li ng-repeat="field in fields">
{{field}}
<ul>
<li ng-repeat="(name, value) in field">
{{name}}:{{value}}
</li>
</ul>
</li>
</ul>
</li>
</ul>
</div>

AngularJS Filed nested array of objects with array of objects

I'm trying to filter a nested array of objects with my own objects, by idSubject. But I'm not getting the right result.
I have articles (which have subjects)
And a array of objects (which are the subjects I want to filter the articles with)
Data looks like this:
So I'm trying to filter the array of articles by its subjects.
I tried the following:
<div class="panel panel-default"
ng-repeat="searchArticle in searchArticles | filter: {subjects: filterSubjects} as articleSearchResult">
So filterSubjects is the second screenshot and SearchArticles is the first screenshot.
Without much luck.
Hope you can help, please tell me if things are still unclear.
This custom filter will help you.
Example : http://plnkr.co/edit/jMizCLxPH6DtDA5wL15Q?p=preview
HTML:
<body ng-app="myApp">
<div ng-controller="MainCtrl">
<h2>Select Subjects</h2>
<div ng-repeat="subject in subjects">
<label>
<input type="checkbox" ng-model="filterSubjects[subject.id]" ng-true-value="'{{subject.id}}'" ng-false-value="''">{{subject.name}}</label>
</div>
<h2>Filtered Articles</h2>
<div ng-repeat="searchArticle in searchArticles | subjectFilter:filterSubjects">{{searchArticle.name}}</div>
</div>
</body>
JS:
var app = angular.module('myApp', []);
app.controller('MainCtrl', function($scope) {
$scope.searchArticles = [{
"name": "Article1",
"sid": "1"
}, {
"name": "Article2",
"sid": "1"
}, {
"name": "Article3",
"sid": "2"
}];
$scope.subjects = [{
"name": "Subject1",
"id": "1"
}, {
"name": "Subject2",
"id": "2"
}];
$scope.filterSubjects = [];
});
app.filter('subjectFilter', function() {
return function(articles, filterSubjects) {
filtered = articles.filter(function(e){return filterSubjects.indexOf(e.sid) >= 0},filterSubjects);
return filtered;
}
});
if you want to filter based on object :
var app = angular.module('myApp', []);
app.controller('MainCtrl', function($scope) {
$scope.searchArticles = [{
"name": "Article1",
"sid": "1"
}, {
"name": "Article2",
"sid": "1"
}, {
"name": "Article3",
"sid": "2"
}];
$scope.subjects = [{
"name": "Subject1",
"id": "1"
}, {
"name": "Subject2",
"id": "2"
}];
$scope.filterSubjects = [{
"name": "Subject1",
"id": "1"
}, {
"name": "Subject1",
"id": "2"
}];
});
app.filter('subjectFilter', function() {
return function(articles, filterSubjects) {
var sFiltered = [];
for (var i = 0; i < filterSubjects.length; i++) {
sFiltered.push(filterSubjects[i].id);
}
var filtered = articles.filter(function(e) {
return sFiltered.indexOf(e.sid) >= 0;
}, sFiltered);
return filtered;
}
});

AngularJS: filter ng-repeat by array with multiple objects

I have a ng-repeat filtered by the parameters city & first_name, as in the example:
vm.search = {
"city": "D.C.",
"first_name": "Chu"
};
<li ng-repeat="item in user | filter: search">...
var appname = 'app';
var dependencies = [];
angular.module(appname, dependencies);
var app = angular.module(appname);
var userC = function ($scope) {
var vm = $scope;
vm.search = {
"city": "D.C.",
"first_name": "Chu"
};
vm.user = [
{
"id": 1,
"first_name": "Chuck",
"last_name": "Norris",
"city": "Washington D.C.",
"languages": [
{
"id": "41",
"name": "English"
},
{
"id": "73",
"name": "Japanese"
}
]
}
];
};
app.controller('userC', userC);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<ul ng-app="app" ng-controller="userC">
<li ng-repeat="item in user | filter: search track by item.id">
{{ item.first_name }} {{ item.last_name }}
</li>
</ul>
But now I need to filter by languages which is an array of objects:
vm.search = {
"languages": [
{
"name": "Japanese"
}
]
};
<li ng-repeat="item in user | filter: search">...
var appname = 'app';
var dependencies = [];
angular.module(appname, dependencies);
var app = angular.module(appname);
var userC = function ($scope) {
var vm = $scope;
vm.search = {
"languages": [
{
"name": "Japanese"
}
]
};
vm.user = [
{
"id": 1,
"first_name": "Chuck",
"last_name": "Norris",
"city": "Washington D.C.",
"languages": [
{
"id": "41",
"name": "English"
},
{
"id": "73",
"name": "Japanese"
}
]
}
];
};
app.controller('userC', userC);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<ul ng-app="app" ng-controller="userC">
<li ng-repeat="item in user | filter: search track by item.id">
{{ item.first_name }} {{ item.last_name }}
</li>
</ul>
As you can see, there are no results because the default filter doesn't do the job.
Can someone help me achieving a filter that suits this last case?
Both examples are here:
http://codepen.io/anon/pen/KVvQrq
http://codepen.io/anon/pen/JGypqx
You have to declare languages as an object:
vm.search = {
"languages":
{
"name": "Japanese"
}
};
Here's the codepen.
Update after comment: if you want a more complex filter, you can use a function instead of an object. Angular will call Array.prototype.filter() on your user array, so your function could be defined this way:
var allowedLanguages = [
"Japanese",
"Brazilian Portuguese"
];
vm.search = function(item) {
for (var i = 0; i < item.languages.length; i++) {
if (allowedLanguages.indexOf(item.languages[i].name) !== -1) {
return true;
}
}
return false;
};

Angular filtering object based on array of strings

I'd like to be able to filter an entire object based on an array of strings. Currently the default filter will search an entire object based on a single string value, but not with an array of strings.
current jsfiddle
<div ng-controller="myController">
<div>
<ul determine-filtering>
<li get-filter-tag active-state="false" tag="{{button}}"
ng-repeat="button in buttons">
{{button}}
</li>
</ul>
<hr/>
<ul>
<li ng-repeat="item in content | filter:filterArray">
{{item.data.headline}}
</li>
</ul>
</div>
</div>
app.js
var testapp = angular.module('testapp', [])
.filter('inArray', function($filter){
return function(list, arrayFilter){
if(arrayFilter.length > 0){
console.log(arrayFilter);
return $filter("filter")(list, function(listItem){
return arrayFilter.indexOf(listItem) != -1;
});
}else{
return $filter("filter")(list, function(listItem){
return arrayFilter.indexOf(listItem) == -1;
});
}
};
})
.directive('getFilterTag', function () {
return {
link: function postLink(scope, element, attrs) {
element.on('click', function(){
var tag = attrs.tag;
var filterArray = scope.filterArray;
if(filterArray.indexOf(tag) === -1){
scope.filterArray.push(tag);
}else{
filterArray.splice(filterArray.indexOf(tag), 1);
}
scope.$apply();
});
}
};
})
.directive('activeState', function () {
return {
link: function (scope, element, attrs) {
element.on('click', function(){
attrs.activeState = !attrs.activeState;
if(!attrs.activeState){
$(this).addClass('active');
}else{
$(this).removeClass('active');
};
});
}
};
})
.controller('myController', function($scope){
$scope.filterArray = [];
$scope.buttons = ['corn', 'vegetable', 'onion'];
$scope.content = [
{
"type": [
"recipe"
],
"data": {
"prepTimeInMinutes": 10,
"serves": "6 to 8",
"headline": "North Carolina Piedmont Slaw",
"ingredients": [
{
"item": "medium head cabbage",
"quantity": {
"number": 1
},
"notes": "cored and chopped (5 to 6 cups)"
},
{
"unit": "cup",
"item": "ketchup",
"quantity": {
"number": 1
}
},
{
"unit": "tbsp.",
"item": "sugar",
"quantity": {
"number": 3
}
},
{
"unit": "tbsp.",
"item": "apple cider vinegar",
"quantity": {
"number": 1
}
},
{
"unit": "tsp.",
"item": "kosher salt",
"quantity": {
"fraction": {
"display": "½",
"denominator": 2,
"numerator": 1
}
}
},
{
"unit": "tsp.",
"item": "black pepper",
"quantity": {
"fraction": {
"display": "½",
"denominator": 2,
"numerator": 1
}
},
"notes": "freshly ground"
},
{
"item": "Generous dash hot sauce, such as Texas Pete Hot Sauce or Tabasco brand"
}
],
"description": "",
"cookTimeInMinutes": 180,
"categories": {
"Dish Type": [
"Side"
],
"Main Ingredient": [
"Vegetable"
]
},
"cookingDirections": [
{
"step": "Place the cabbage in a large bowl."
},
{
"step": "Combine the ketchup, sugar, vinegar, salt, pepper and hot sauce in a liquid measuring cup. Pour over the cabbage and toss to coat thoroughly. Cover and refrigerate for at least 3 hours, and preferably overnight, before serving."
},
{
"step": "Serve on top of the pulled pork"
}
]
}
}
]
} );
I have a custom filter which worked with arrays, but not with arrays with nested objects. What is the best approach to do this kind of filtering? Is there anything the $filter service already provides for searching based on arrays?
If you need to filter an object based on an array of strings (matching the objects properties) I would look into lodash#omit.
Usage:
var obj = { a: 'a', b: 'b', c: 'c' };
var arr = ['a', 'c'];
_.omit(obj, arr); // { b: 'b' }
I'm not sure whether omit supports deep/nested objects. If not, you could compose it with an iterator to determine whether the given key of an object is an object itself and run another omit on that.

Resources