Reputation: 938
Scratching my head now for 2 hours. Maybe I'm tired or maybe I don't understand what I'm doing. Anyway, I've got an array of blogposts. Which looks like this:
[
{
'title': 'first post',
'tags': [
{ 'name': 'Tag 1', 'slug': 'tag-1' }
]
},
{
'title': 'second post',
'tags': [
{ 'name': 'Tag 1', 'slug': 'tag-1' },
{ 'name': 'Tag 3', 'slug': 'tag-3' }
]
},
{
'title': 'third post',
'tags': [
{ 'name': 'Tag 2', 'slug': 'tag-2' }
]
}
]
And also an array containing my tags like this.
[
{'title': 'Tag 1', 'slug':'tag-1'},
{'title': 'Tag 2', 'slug':'tag-2'},
{'title': 'Tag 3', 'slug':'tag-3'},
{'title': 'Tag 4', 'slug':'tag-4'}
]
And I am doing an regular angular ng-repeat like this to show all my blogpost tags:
<ul>
<li ng-repeat="tag in blog.tags">
<h3>{{ tag.title }}</h3>
</li>
</ul>
Now, I would like to add a nested repeater which only shows blogposts from the variable blog.posts
that contains the current tag.
Something like this:
<ul ng-controller="BlogComponent as blog">
<li ng-repeat="tag in blog.tags">
<h3>{{ tag.title }}</h3>
<ul>
<li ng-repeat="post in blog.posts | filter: tag.slug IN post.tags">
<span>{{ post.title }}</span>
</li>
</ul>
</li>
</ul>
But I cannot seem to get it working. I think it SHOULD be easy. Because in my mind it is a quite simple task. to filter out unwanted results based on a string and an array.
Wanted/Exptected output:
<ul>
<li>
<h3>Tag 1</h3>
<ul>
<li>first post</li>
<li>second post</li>
</ul>
</li>
<li>
<h3>Tag 2</h3>
<ul>
<li>third post</li>
</ul>
</li>
<li>
<h3>Tag 3</h3>
<ul>
<li>second post</li>
</ul>
</li>
</ul>
Upvotes: 1
Views: 640
Reputation: 31005
Using the built-in functionality, you can do it like this:
<ul ng-controller="BlogComponent as blog">
<li ng-repeat="tag in blog.tags">
<h3>{{ tag.title }}</h3>
<ul>
<li ng-repeat="post in blog.posts | filter: {tags: {slug: tag.slug}}">
<span>{{ post.title }}</span>
</li>
</ul>
</li>
</ul>
See it working here: https://plnkr.co/edit/pQZse1hUnnzyfneIlpMu?p=preview
Documentation for the filter is here: https://docs.angularjs.org/api/ng/filter/filter
Or, if you want Tag 4 to be hidden because it has no matching posts, you could do something like this:
<div ng-controller="BlogComponent as blog">
<div ng-repeat="tag in blog.tags">
<div ng-repeat="post in blog.posts | filter: {tags: {slug: tag.slug}}">
<h3 ng-if="$first">{{ tag.title }}</h3>
<li>{{ post.title }}</li>
</div>
</div>
</div>
Upvotes: 1
Reputation: 235
You could make a custom filter instead of using "filter: expression". What you can do create a filter that takes the tags and posts as arguments and returns the array with filtered items.
myApp.filter('myFilter', function () {
return function (posts, tag) {
var newPosts = [];
for (var i = 0; i < posts.length; i++)
for (var j = 0; j < post.tags.length; j++)
if (posts[i].tags[j].slug === tag.slug)
newPosts.push(posts[i]);
return newPosts;
}
});
And then
<li ng-repeat="post in blog.posts | myFilter: tag">
<span>{{ post.title }}</span>
</li>
Upvotes: 1