AngularJS ng-repeat to display group names from JSON data - angularjs

How Display stores,bookmarks,favorites using below JSON Data
JSON data (vm.bookmarks):
[
{
"category": "stores",
"title": "store1",
"link": "http://www.store1.com",
},
{
"category": "stores",
"title": "store1",
"link": "http://www.store2.com",
},
{
"category": "bookmarks",
"title": "bookmark1",
"link": "http://www.bookmark1.com",
},
{
"category": "bookmarks",
"title": "bookmark2",
"link": "http://www.bookmark2.com",
},
{
"category": "bookmarks",
"title": "bookmark3",
"link": "http://www.bookmark3.com",
},
{
"category": "favorites",
"title": "favorites1",
"link": "http://www.favorites1.com",
},
{
"category": "favorites",
"title": "favorites2",
"link": "http://www.favorites2.com",
}
]
I want to list only categories' names using ng-repeat:
<div ng-repeat="item in vm.bookmarks|groupBy:'category'">
<h2>{{item.category}}</h2>
</div>
I want this to be displayed:
stores
bookmarks
favorites
But it displays nothing! What am I doing wrong?
P.S
I was using filters without injecting anything, like this:
<div ng-repeat="item in vm.bookmarks|filter:{category:'flyers'}" >
{{item.title}}
</div>
Not sure if I need to inject angular-filter to use groupBy filter - why?

You do not need to use (key, value) , also you need to inject angular.filter as dependency
var MyApp = angular.module("MyApp",['angular.filter']);
<ul class="nav nav-tabs" data-tabs="tabs"
ng-repeat="bookmark in vm.bookmarks|groupBy:'category'">
<li>{{bookmark.category}}</li>
</ul>
DEMO
var app = angular.module("myApp", ['angular.filter']);
app.controller("SimpleController", function($scope) {
this.bookmarks = [
{
"category": "stores",
"title": "store1",
"link": "http://www.store1.com",
},
{
"category": "stores",
"title": "store1",
"link": "http://www.store2.com",
},
{
"category": "bookmarks",
"title": "bookmark1",
"link": "http://www.bookmark1.com",
},
{
"category": "bookmarks",
"title": "bookmark2",
"link": "http://www.bookmark2.com",
},
{
"category": "bookmarks",
"title": "bookmark3",
"link": "http://www.bookmark3.com",
},
{
"category": "favorites",
"title": "favorites1",
"link": "http://www.favorites1.com",
},
{
"category": "favorites",
"title": "favorites2",
"link": "http://www.favorites2.com",
}
];
var vm = this;
});
<!DOCTYPE html>
<html>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-filter/0.5.16/angular-filter.js" > </script>
<body ng-app="myApp">
<div>
<div data-ng-controller="SimpleController as vm">
<ul class="nav nav-tabs" data-tabs="tabs"
ng-repeat="(key, value) in (vm.bookmarks|groupBy:'category')">
<div ng-repeat="cat in value | unique:'category' ">
<h1> {{cat.category}}</h1>
</div>
</ul>
</div>
</div>
</body>
</html>

Related

I need a helper function to loop through complex object arrays with ngFor

I'm working on setting up a loop in angular and I'm quite new to this. Normally I'd be able to do it no problem but since I was given a weird data object to work with I'm terribly stuck. My code is as follows.
So far I can get the list from "children" at the top of the object but I cant go any further.
Here is my data
{
"type": "categoryGroup",
"children": [
"Apples",
"Bananas",
"Oranges"
],
"Apples": {
"type": "categorySubgroup",
"children": [
"Golden Delicious",
"Granny Smith",
"Macintosh"
],
"Golden Delicious": {
"type": "articleList",
"articles": [
{
"key": "article-1",
"name": "Article 1"
},
{
"key": "article-2",
"name": "Article 2"
}
]
},
"Granny Smith": {
"type": "articleList",
"articles": [
{
"key": "article-1",
"name": "Article 1"
},
{
"key": "article-2",
"name": "Article 2"
}
]
},
"Macintosh": {
"type": "articleList",
"articles": [
{
"key": "article-1",
"name": "Article 1"
},
{
"key": "article-2",
"name": "Article 2"
}
]
}
},
"Bananas": {
"type": "categorySubgroup",
"children": [
"Lady's Finger",
"Cavendish Bananas"
],
"Lady's Finger": {
"type": "articleList",
"articles": [
{
"key": "article-1",
"name": "Article 1"
},
{
"key": "article-2",
"name": "Article 2"
}
]
},
"Cavendish Bananas": {
"type": "articleList",
"articles": [
{
"key": "article-1",
"name": "Article 1"
},
{
"key": "article-2",
"name": "Article 2"
}
]
}
},
"Oranges": {
"type": "categorySubgroup",
"children": [
"Blood Orange"
],
"Blood Orange": {
"type": "articleList",
"articles": [
{
"key": "article-1",
"name": "Article 1"
},
{
"key": "article-2",
"name": "Article 2"
}
]
}
}
}
Here is the HTML part of my code (which is failing miserably)
<div class="col-md-12" *ngFor="let category of fruit.categories.children">
<div class="card">
<div class="card__header">
<h4 class="card__title">{{ category }}</h4>
</div>
<div class="card__body">
<div class="row">
<div class="col-md-4" *ngFor="let categoryGroup of category.children">
<div class="subheader">{{ categoryGroup }}</div>
<div>
<ul class="resource-list" *ngFor="let categoryItem of categoryGroup.articles">
<li>{{ categoryItem.name }}</li>
</ul>
</div>
</div>
</div>
</div>
</div>
</div>
I would like some help looping down the object arrays, maybe as a helper function using the "children" array. Any thoughts or help would be greatly appreciated. Thanks!
Try out the following code, please.
<div class="col-md-12" *ngFor="let category of fruit.children">
<div class="card">
<div class="card__header">
<h4 class="card__title">{{ category }}</h4>
</div>
<div class="card__body">
<div class="row">
<div class="col-md-4" *ngFor="let categoryGroup of fruit[category].children">
<div class="subheader">{{ categoryGroup }}</div>
<div>
<ul class="resource-list" *ngFor="let categoryItem of fruit[category].articles">
<li>{{ categoryItem.name }}</li>
</ul>
</div>
</div>
</div>
</div>
</div>
</div>
You could get at the data using methods in the component to keep things quite clear. Here's an example object that could be used for testing:
export const data = {
"type": "categoryGroup",
"children": [
"Apples",
"Bananas",
"Oranges"
],
"Apples": {
"type": "categorySubgroup",
"children": [
"Golden Delicious",
"Granny Smith",
"Macintosh"
],
"Golden Delicious": {
"type": "articleList",
"articles": [
{
"key": "article-1",
"name": "Article 1"
},
{
"key": "article-2",
"name": "Article 2"
}
]
},
"Granny Smith": {
"type": "articleList",
"articles": [
{
"key": "article-1",
"name": "Article 1"
},
{
"key": "article-2",
"name": "Article 2"
}
]
},
"Macintosh": {
"type": "articleList",
"articles": [
{
"key": "article-1",
"name": "Article 1"
},
{
"key": "article-2",
"name": "Article 2"
}
]
}
},
"Bananas": {
"type": "categorySubgroup",
"children": [
"Lady's Finger",
"Cavendish Bananas"
],
"Lady's Finger": {
"type": "articleList",
"articles": [
{
"key": "article-1",
"name": "Article 1"
},
{
"key": "article-2",
"name": "Article 2"
}
]
},
"Cavendish Bananas": {
"type": "articleList",
"articles": [
{
"key": "article-1",
"name": "Article 1"
},
{
"key": "article-2",
"name": "Article 2"
}
]
}
},
"Oranges": {
"type": "categorySubgroup",
"children": [
"Blood Orange"
],
"Blood Orange": {
"type": "articleList",
"articles": [
{
"key": "article-1",
"name": "Article 1"
},
{
"key": "article-2",
"name": "Article 2"
}
]
}
}
}
Now, we could import this data and create some getters (in app.component.ts for example):
import { Component } from '#angular/core'
import { data } from './data'
#Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: [ './app.component.css' ]
})
export class AppComponent {
data = data
getFruits() {
return data.children
}
getFruit(fruit: string) {
return data[fruit]
}
getVarieties(fruit) {
return data[fruit].children
}
getVariety(fruit, variety) {
return data[fruit][variety]
}
getArticles(fruit, variety) {
return data[fruit][variety].articles
}
getArticle(fruit, variety, article) {
return data[fruit][variety][article]
}
}
In the template, the properties could now be used like this:
<h1>Fruit Data</h1>
<p><span class="key">type:</span> {{ data.type }}</p>
<p><span class="key">children:</span> {{ data.children }}</p>
<hr>
<div class="fruit" *ngFor="let fruit of getFruits()">
<h2>{{ fruit }}</h2>
<p><span class="key">type:</span> {{ getFruit(fruit).type }}</p>
<p><span class="key">children:</span> {{ getFruit(fruit).children }}</p>
<div class="variety" *ngFor="let variety of getVarieties(fruit)">
<h3>{{ variety }}</h3>
<p><span class="key">type:</span> {{ getVariety(fruit, variety).type }}</p>
<p><span class="key">articles:</span> {{ getArticles(fruit, variety) | json }}</p>
<div class="article" *ngFor="let article of getArticles(fruit, variety)">
<p><span class="key">key:</span> {{ article.key }}</p>
<p><span class="key">name:</span> {{ article.name }}</p>
</div>
</div>
</div>

Multiple filter with same value Angularjs

I have an JSON object like this
$scope.list = [{
"ID": 1,
"Name": "NAME1",
"Category": "Category1",
"Code": "Code1"
}, {
"ID": 2,
"Name": "NAME2",
"Category": "Category1",
"Code": "Code2"
}, {
"ID": 3,
"Name": "NAME3",
"Category": "Category1",
"Code": "Code3"
}, {
"ID": 4,
"Name": "NAME4",
"Category": "Category3",
"Code": "Code4"
}, {
"ID": 5,
"Name": "NAME5",
"Category": "Category3",
"Code": "Code5"
}]
And I have just one input. I want to filter the ng repetive directive with only the objects that have values similar to "Name" or "Category" properties. How can I do that? For example:
<input type="text" ng-model="searchText">
<div ng-repeat="obj in list | filter:{Name:searchText.name}"
| filter:{Category:searchText.category}">
</div>
I dont want to search by Code propertie.
Thanks
You can have a model variable and use it for filter,
DEMO
angular.module('myApp', [])
.controller('myCtrl', function($scope){
$scope.list = [{
"ID": 1,
"Name": "NAME1",
"Category": "Category1",
"Code": "Code1"
}, {
"ID": 2,
"Name": "NAME2",
"Category": "Category1",
"Code": "Code2"
}, {
"ID": 3,
"Name": "NAME3",
"Category": "Category1",
"Code": "Code3"
}, {
"ID": 4,
"Name": "NAME4",
"Category": "Category3",
"Code": "Code4"
}, {
"ID": 5,
"Name": "NAME5",
"Category": "Category3",
"Code": "Code5"
}];
$scope.search = function (row) {
return (angular.lowercase(row.Name).indexOf($scope.searchText || '') !== -1 || angular.lowercase(row.Category).indexOf($scope.searchText || '') !== -1);
};
});
<!DOCTYPE html>
<html ng-app='myApp'>
<head>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.3.2/angular.min.js"></script>
<meta charset="utf-8">
<title>JS Bin</title>
</head>
<body ng-controller='myCtrl'>
Search: <input ng-model="searchText">
<table id="searchTextResults">
<tr><th>Name</th><th>Category</th></tr>
<tr ng-repeat="item in list | filter:search">
<td>{{item.Name}}</td>
<td>{{item.Category}}</td>
</tr>
</table>
</body>
</html>

Parsing error when trying to get JSON file

I have a web app I'm building using AngularJS. On the table of contents page, I want to display a list of all the articles published. I keep getting this error:
SyntaxError: Unexpected token :
at Object.parse (native)
at fromJson
app.js
var webApp = angular.module('webApp', ['ui.router']);
webApp.controller('TableofContentController', function($scope, $http) {
$http.get('articles.json')
.then(function(res){
$scope.articles = res.data;
});
});
articles.json
{
"articles": [
{
"id": "1",
"title": "Article Title",
"categories": [ "category": "1",
"category": "2" ],
},
{
"id": "2",
"title": "Article Title",
"categories": [ "category": "1",
"category": "2" ],
},
...etc..
]
}
relevant HTML
<div class="row" ng-controller="TableofContentController">
<div class="medium-12 columns" role="content">
<div class="medium-9 columns">
<article>
<div class="main">
<ul>
<li ng-repeat="article in articles">
<a ui-sref="">{{title}}</a>
</li>
....etc.....
Any suggestions on what I can do to fix this parsing error? I think I have JSON all formatted correctly, but I would appreciate any insight.
This section
"categories": [ "category": "1",
"category": "2" ],
should be an array of objects I think, like this
"categories": [ {"category": "1"},
{"category": "2"} ],
Syntax checking tools like jshint can be very helpful in finding problems like this

Loading json data into angularjs ng-repeat and outside of ng-repeat from same json file

i'm new to angular and a little lost. i'm able to load the data and display it, but i'm confused about loading other data that is not part of the ng-repeat i have set up from the same json file. here is what i have so far.
i would like to not use $scope.titleName = "John Doe"; $scope.infotext = "some more info" and have this info come from within the json file.
thanks for any help you can give.
var app = angular.module("myApp", []);
app.controller('something', function ($scope, $http){
$http.get('site.json').success(function(data) {
$scope.sites = data;
$scope.titleName = "John Doe";
$scope.infotext = "some more info"
});
});
/* json file content */
[
{
"name": "tim",
"image": "/features/home-1.jpg",
"link": "http://www.bbc.co.uk"
},
{
"name": "don",
"image": "/features/home-1.jpg",
"link": "http://www.bbc.co.uk"
},
{
"name": "Mike",
"image": "/features/home-1.jpg",
"link": "http://www.bbc.co.uk"
},
{
"sub": {"titleName": "Homer", "infotext":"two"}
}
]
<body ng-app="myApp" ng-controller="something" >
<div class="wrapper">
<h1>{{titleName}}</h1>
<p class="info">{{infotext}}</p>
<div class="big" ng-repeat="site in sites ">
<a href="{{site.link}}" target="_blank">
<img src="{{site.image}}">
</a>
<h2>{{site.name}}</h2>
</div>
</div>
</body>
Change your JSON because the last object of the array is different from sites, I suggest to have a JSON like this :
{
"sites": [{
"name": "tim",
"image": "/features/home-1.jpg",
"link": "http://www.bbc.co.uk"
}, {
"name": "don",
"image": "/features/home-1.jpg",
"link": "http://www.bbc.co.uk"
}, {
"name": "Mike",
"image": "/features/home-1.jpg",
"link": "http://www.bbc.co.uk"
}],
"sub": {
"titleName": "Homer",
"infotext": "two"
}
}
You have also to modify your controller
app.controller('something', function ($scope, $http){
$http.get('site.json').success(function(data) {
$scope.sites = data.sites;
$scope.titleName = data.sub.titleName;
$scope.infotext = data.sub.infotext;
});
});

Order post By Date inside ng-repeat in View

I am working on an angular app . here i need to show data in date order for user timeline
JS:
$scope.comments = [{"_id":"535e912cc6b93c7b30479454",
"created_at":"2014-04-28 23:04:36",
"post_id":"535e912cc6b93c7b30479453",
"type":"story",
"story":"[{"_id":"535e912cc6b93c7b30479454",
"title":"test story",
"content":"this is my story...",
"created_at":2014-04-30 22:04:36"}]",
"article":"[]"
},
{"_id":"535e912cc6b93c7b30479454",
"created_at":"2014-04-25 23:04:36",
"post_id":"535e912cc6b93c7b30479453",
"type":"article"
"article":"[{"_id":"535e912cc6b93c7b30479454",
"title":"test article",
"content":"this is my article...",
"created_at":2014-04-30 22:04:36"}]",
"story":"[]"
},----
//so on
]
View:
<div ng-repeat = "data in comments">
<div class="time">
<span>{{data.created_at | DateFiltertoIso | date:'MMM-dd-yy'}}
<div>
<div ng-switch-on="data.type">
<div ng-switch-when="story">
//switch layout adn get further story data by post_id
</div>
</div>
<div ng-switch-on="data.type">
<div ng-switch-when="article">
//switch layout adn get further article data by post_id
</div>
</div>
</div>
Expected Output is like
Apr-04-14
post1
post2
/all post for that date
Apr-01-14
post5
post6
//so on
I am getting
Apr-04-2014
post1
Apr-04-2014
post2
Apr-04-2014
post3
I am newbie to angular. Any Help would be helpfull
Try this
Working Demo
Html
<div ng-controller="MyCtrl">
<div ng-repeat="data in flattenedResults">
<div class="time"> <span>
<b>{{data.created_at | badDateToISO | date:'MMM-d-yy'}} </b></span>
<div>
<u ng-show="data.story.length>0">Stories</u>
<div ng-repeat="story in data.story">
{{story.title}}{{story.created_at}}
</div>
<u ng-show="data.article.length>0">Articles</u>
<div ng-repeat="article in data.article">
{{article.title}}
</div>
Script
var myApp = angular.module('myApp', []);
myApp.filter('badDateToISO', function () {
return function (badTime) {
var goodTime = badTime.replace(/(.+) (.+)/, "$1T$2Z");
return goodTime;
};
});
myApp.controller('MyCtrl', function ($scope) {
$scope.flattenedResults = [];
$scope.comments = [{
"_id": "535e912cc6b93c7b30479454",
"created_at": "2014-04-28 23:04:36",
"post_id": "535e912cc6b93c7b30479453",
"type": "story",
"story": [{
"_id": "535e912cc6b93c7b30479454",
"title": "test story 1",
"content": "this is my story... 2",
"created_at": "2014-04-30 22:04:36"
}],
"article": "[]"
}, {
"_id": "535e912cc6b93c7b30479454",
"created_at": "2014-04-28 23:04:36",
"post_id": "535e912cc6b93c7b30479453",
"type": "article",
"article": [{
"_id": "535e912cc6b93c7b30479454",
"title": "test article 33",
"content": "this is my article... 33",
"created_at": "2014-04-30 22:04:36"
}],
"story": "[]"
}, {
"_id": "535e912cc6b93c7b30479454",
"created_at": "2014-04-25 23:04:36",
"post_id": "535e912cc6b93c7b30479453",
"type": "article",
"article": [{
"_id": "535e912cc6b93c7b30479454",
"title": "test article 1",
"content": "this is my article... 1",
"created_at": "2014-04-30 22:04:36"
}],
"story": "[]"
}, {
"_id": "535e912cc6b93c7b30479454",
"created_at": "2014-04-28 23:04:36",
"post_id": "535e912cc6b93c7b30479453",
"type": "story",
"story": [{
"_id": "535e912cc6b93c7b30479454",
"title": "test story 2",
"content": "this is my story... 2",
"created_at": "2014-04-30 22:04:36"
}],
"article": "[]"
}, {
"_id": "535e912cc6b93c7b30479454",
"created_at": "2014-04-25 23:04:36",
"post_id": "535e912cc6b93c7b30479453",
"type": "article",
"article": [{
"_id": "535e912cc6b93c7b30479454",
"title": "test article 2",
"content": "this is my article... 2",
"created_at": "2014-04-30 22:04:36"
}],
"story": "[]"
}];
$scope.jsonFlatten = function () {
$scope.dates = [];
$scope.comments.reduce(function (result, item) {
$scope.dates.push(item.created_at);
}, 0);
$scope.dates = _.uniq($scope.dates);
angular.forEach($scope.dates, function (dateValue, dateKey) {
var obj = {};
obj.created_at = dateValue;
var articleValues = [];
var storyValues = [];
angular.forEach($scope.comments, function (value, key) {
if (dateValue === value.created_at) {
obj._id = value._id;
obj.post_id = value.post_id;
if (value.type === 'story') {
angular.forEach(value.story, function (storyValue, storyKey) {
storyValues.push(storyValue)
});
} else if (value.type === 'article') {
angular.forEach(value.article, function (articleValue, articleKey) {
articleValues.push(articleValue)
});
}
}
});
obj.story = storyValues;
obj.article = articleValues;
$scope.flattenedResults.push(obj);
});
};
$scope.jsonFlatten(); //calling the method jsonFlatten() and making the flatten json
});

Resources