Angular using ng-repeat variable in nested ng-repeat - angularjs

I have an ng-repeat which iterates over an array of values:
var englishList = ["abo", "ser", "vol", "con", "giv", "blo"];
$scope.englishList = englishList;
Is there a way to loop over these values in an ng-repeat and use the returned value as part of a nested ng-repeat?
<div ng-repeat="api in englishList">
<div ng-repeat="result in searchData.abo | filter:searchText">
<li>{{result.title}} {{result.shortname}}</li>
</div>
</div>
Ideally, I'd like this line to interpolate the each ng-repeat value from $scope.englishList:
<div ng-repeat="result in searchData.{{api}} | filter:searchText">
Is there a way to do this in angular?

You should be able to do something like this, surely:
<div ng-repeat='api in englishList'>
<div ng-repeat='item in searchData[api]'>
<!-- uses the value of 'api' as a key in 'searchData' -->
<!-- you do not need to use interpolation here as these are already expressions -->
</div>
</div>
I can't really give a complete example as your code is not exactly obvious in how you would want to use the nested type, but the above snippet should give you an idea of HOW to use nested repeats.
I would advise you use an object model like so
{ "api": {
"foo": [ "bar", "baz", "qux" ]
}}
Rather than having two different arrays. This should make it less brittle. Remember that your view's logic should ideally be as simple as possible and it shouldn't have to do much manipulation on the data given to it to work. I would say that iterating one array and then iterating another using the values of array 1 as keys of array 2 is maybe a bit too much for the view to do.

Just use the bracket notation to dynamically access a property :
<div ng-repeat="api in englishList">
<div ng-repeat="result in searchData[api] | filter: searchText" >
<li>{{result.title}}, {{result.shortname}}</li>
</div>
</div>
Snippet :
angular.module('demoApp', []).controller('DemoController', function ($scope) {
$scope.englishList = ["abo", "ser", "vol", "con"];;
$scope.searchData = {
abo: [{
title: 'title abo',
shortname: 'shortname abo'
}],
ser: [{
title: 'title ser 1',
shortname: 'shortname ser 1'
}, {
title: 'title ser 2',
shortname: 'shortname ser 2'
}],
vol: [{
title: 'title vol',
shortname: 'shortname vol'
}],
con: [{
title: 'title con',
shortname: 'shortname con'
}]
};
});
p {
font-weight: bold;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="demoApp" ng-controller="DemoController">
<div>Search <input type="text" ng-model="searchText"/></div>
<div ng-repeat="api in englishList">
<p>{{api}}</p>
<div ng-repeat="result in searchData[api] | filter: searchText" >
<li>{{result.title}}, {{result.shortname}}</li>
</div>
</div>
</div>

Related

Hide headers in multiple ng-repeat if no values during filtering

I'm struggling with angularjs! Here's the problem. I've a list of employees from different company to show. Data are like these:
[
{
name : "company1",
employees : [
{ name : "emp1"},
{...}
]
},
{ .. }
]
I show them using two ng-repeat:
<div ng-repeat="company in companies ">
<div class="header">{{company.name}}</div>
<div ng-repeat="employee in company.employees | filter:search">
{{employee.name}}
</div>
</div>
Here we are, I want to avoid, during filtering the headers of company with no employees.
Hope you guys are smarter than me :)
<div ng-repeat="company in companies ">
<div class="header" ng-show="results.length>0"> {{company.name}}</div>
<div ng-repeat="employee in company.employees | filter:search as results">
{{employee.name}}
</div>
Explaination: after filtering your filtered data will be stored in ressults , which we can use to decide whether to show company name or not
Try this, I also attached demo.
ng-show="(company.employees | filter:search).length"
var app = angular.module('app', []);
app.controller('myctrl', function() {
var vm = this;
vm.companies = [{
name: "company1",
employees: [{
name: "emp1"
}, {
name: "poiuy"
}, {
name: "asdf"
}]
}, {
name: "company2",
employees: [{
name: "ghj"
}, {
name: "jkl"
}, {
name: "ooo"
}]
}];
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.7/angular.min.js"></script>
<body ng-app="app">
<div ng-controller="myctrl as ct">
<input ng-model="ct.search">
<div ng-repeat="company in ct.companies ">
<div class="header" ng-show="(company.employees | filter:ct.search).length">{{company.name}}</div>
<div ng-repeat="employee in company.employees | filter:ct.search">
{{employee.name}}
</div>
</div>
</div>
</body>

angularjs filter on nested objects

I am quite new with angularjs so I am not sure if what I am trying to do is the right way. Basically I want to display in my page a nested object, and a filter, this way the user can easily type keywords on an input and the content get filtered, to only display the recods that get found by the filter
However I notice that the filter gets the whole parent object and i was expecting only display the record, so with the following code, if i search for Japan it will display Sydney, Melbourne and los angeles.
Javascript
<script type="text/javascript">
var demoApp = angular.module('demoApp',['ngSanitize']);
demoApp.controller('simpleC',['$scope', function ($scope){
$scope.info = [
{name: 'Documents',links: [
{linkname:'title1',linknamesublink:[
{namesublink:'document 1', description: 'Sydney'},
{namesublink:'document 2', description: 'Tokyo <b>Japan</b>'}
]},
{linkname:'title2',linknamesublink:[
{namesublink:'document 3', description: 'Melbourne'},
{namesublink:'document 4', description: 'Los Angeles'}
]}
]},
{name: 'Video',links: [
{linkname:'title1',linknamesublink:[
{namesublink:'video 1', description: 'California'},
{namesublink:'video 2', description: 'San Francisco <b> USA</b>'}
]},
{linkname:'title2',linknamesublink:[
{namesublink:'video 3', description: 'South America'},
{namesublink:'video 4', description: 'Northern <b>Europe</b>'}
]},
{linkname:'title3',linknamesublink:[
{namesublink:'video name 5', description: 'Africa'},
{namesublink:'video name 6', description: 'Bangkok <b>Thailand</b>'}
]}
]},
];
}]);
</script>
html:
<div class="container" ng-app="demoApp">
<br /><input type="text" class="form-control" ng-model="search" >
<div ng-controller="simpleC">
<div ng-repeat="i in info | filter:search" >
{{i.name}} :
<div ng-repeat="link in i.links">
{{link.linkname}}
<div ng-repeat="sublink in link.linknamesublink">
{{sublink.namesublink}}: <!--{{sublink.description}}-->
<span ng-bind-html="sublink.description"></span>
</div>
</div>
</div>
</div>
</div>
Follow this example
http://www.whatibroke.com/?p=857
You can use filter in ng-repeat to filter items by property or write a filter yourself.
The author want to filter postcode property by the value of searc_postcode. So, he wrote //filter {postcode : search_postcode} //
Ps. Sorry, I misinterpret your question.
Write your own filter function. This way, you have total control over what is returned. https://docs.angularjs.org/api/ng/filter/filter
module.filter('searchfilter', function() {
return function(searchexpr) {
var filteredList = ['my', 'filtered', 'result'];//implement yourself
return filteredList;
};
});
and use searchfilter instead of filter in your markup.
Or, try to use a filter function as described here: http://fdietz.github.io/recipes-with-angular-js/common-user-interface-patterns/filtering-and-sorting-a-list.html (as far as I can tell, you didn't define a search function, i.e. the first agument for the filter expression).
Modified :
If you want to filter the objects based on any field(say "name"), you can use the below format
<div ng-repeat="i in info" ng-if="search==i.name">

Dependant ng-repeat in AngularJS

I have a following data structure coming from REST:
scope.taglist =
[ { name: "mylist", tags: ["tag1", "tag2", "tag3", ...]}, { name:
"mylist2", tags: ["tag2.1", "tag2.2", "tag2.3", ...]} ]
In order to present the names of the objects I have the following html:
<div>
<select ng-model="tagNameSelection">
<option ng-repeat="tagObj in taglist" value="{{tagObj}}">{{tagObj.name}}</option>
</select>
</div>
<div class="tagdetails">
<!-- present the list of tags from tagNameSelection -->
</div>
Now I am a little bit of a loss on how to present the tags list of
individual object. I am able to present the array in raw format (by
sticking {{tagNameSelection}} inside the tagdetails div) but when I
try to iterate through those with ng-repeat angular gives a error
message.
Oddly enough when I hard-code one of the tag lists to the scope in controller the ng-repeat works flawlessly.
Maybe you interesting something like this:
HTML
<div ng-controller="fessCntrl">
<div>
<select ng-model="tagNameSelection"
ng-options="tagObj as tagObj.name for tagObj in taglist"
ng-change="change(tagNameSelection)"></select>
</div>
<pre>{{tagNameSelection.tags|json}}</pre>
<div class="tagdetails">
<ul ng-repeat="tag in tagNameSelection.tags">
<li>{{tag}}</li>
</ul>
</div>
</div>
Controller
var fessmodule = angular.module('myModule', []);
fessmodule.controller('fessCntrl', function ($scope) {
$scope.change = function (value) {
};
$scope.taglist = [{
name: "mylist",
tags: ["tag1", "tag2", "tag3"]
}, {
name: "mylist2",
tags: ["tag2.1", "tag2.2", "tag2.3"]
}]
});
fessmodule.$inject = ['$scope'];
See Fiddle

AngularJS filter for nested objects

I have an array of objects with arrays of objects in it:
var content = [
{
name: 'Foo',
sub: [{ name: 'Bar' }, { name: 'Foobar' }]
},
...
]
and a template:
<input ng-model="search" />
<div ng-repeat="item in content | filter:search>
{{item.name}}
<div ng-repeat="key in item">
{{key.name}}
</div>
</div>
Now, I use the filter filter to search for string matches, but it applies only to the first ng-repeat directive. How could I include the second directive into the search filter? Thanks in advance.
You can simply apply a second filter expression to your other ng-repeat
<div ng-repeat="key in item | filter:secondFilterExpression">
See docs here http://docs.angularjs.org/api/ng.filter:filter
Ok, I've 'flattened' the object to a simple collection before passing it through the controller to the template, so I don't have to worry about a second ng-repeat cycle. The output is
[{ name : 'foo' }, { name : 'bar' }, { name : 'foobar' }]

How to separate groups in ng-repeat

I have items I want to show, normally by using ng-repeat. I want to show the in some order (easy), but whenever the ordered attribute changes, I want some HTML in-between.
Example: (Fiddle):
<div ng-app ng-controller="Main">
<div ng-repeat="item in items | orderBy:'role'">
{{item.role}} - {{item.name}}
</div>
</div>
function Main($scope){
$scope.items = [{name: 'First', role: 1},
{name: 'Second', role:2},
{name: 'Third', role: 1},
{name: 'Fourth', role: 2}];
}
I want it to print:
1 - First
1 - Third
(some separator kode)
2 - Second
2 - Fourth
You will want to create a function in your scope.
$scope.currentRole = 'something';
$scope.CreateHeader = function(role) {
showHeader = (role!=$scope.currentRole);
$scope.currentRole = role;
return showHeader;
}
And then in your HTML:
<div ng-app ng-controller="Main">
<div ng-repeat="item in items | orderBy:'role'">
<div ng-show="CreateHeader(item.role)">
something here for the header
</div>
{{item.role}} - {{item.name}}
</div>
</div>
The solution by #lucuma only works on the first time through the loop. If Angular refreshes the list, the variable will still be set from the previous loop.
Instead, I added a new attribute to the list (say, header) during initialization:
function Main($scope){
$scope.items = [{name: 'First', role: 1, header: false},
{name: 'Second', role:2, header: false},
{name: 'Third', role: 1, header: true},
{name: 'Fourth', role: 2, header: false}];
}
Then the HTML by #lucuma works:
<div ng-app ng-controller="Main">
<div ng-repeat="item in items | orderBy:'role'">
<div ng-show="item.header"> // <== with this change
something here for the header
</div>
{{item.role}} - {{item.name}}
</div>
</div>
Oh, and you could sort the list once at initialization and remove the orderBy filter.

Resources