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">
Related
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>
Hi I'm new to this framework and I have to change some webapp.
There is already something like this:
<input type="text" class="catalog-search input input--large input--full" ng-model="search">
and
<ul class="catalog-list catalog-scroll">
<li ng-repeat="rodzic in list | groupBy:'styl' | toArray:true | orderBy:!'$key'">
{{rodzic.$key}}
<ul>
<li ng-repeat="dziecko in rodzic | filter:search | bookmark:search" ng-class="{active:isActiveTab(dziecko)}" ng-click="openItem(dziecko)">
{{dziecko.rodzina}}
<b>{{dziecko.page}}</b>
</li>
</ul>
</li>
</ul>
The above code create table of contents for pdf file.When I type some word in input field searching works fine but I can't search by number,let's say I want to find page number 3.
What should I change to be able to find by page number?
Thx in advance.
I see no such problem of searching by numbers. I put a simplified version of your code into Plnkr and I can search by words or numbers - even if the numbers are sometimes numeric values and sometimes strings.
Search on 6 or 7 (which are numeric values) or 3 (which is a string '333'). Both work.
Can you modify my Plunk to show the problem?
Here's my HTML:
<body ng-controller="MainCtrl">
<input type="text" class="catalog-search input input--large input--full" ng-model="search">
<ul class="catalog-list catalog-scroll">
<li ng-repeat="rodzic in list">
{{rodzic.$key}}
<ul>
<li ng-repeat="dziecko in rodzic | filter:search" ng-class="{active:isActiveTab(dziecko)}" ng-click="openItem(dziecko)">
{{dziecko.rodzina}}
<b>{{dziecko.page}}</b>
</li>
</ul>
</li>
</ul>
</body>
Here's my controller with some mock data which I think simulates yours well enough for this demonstration.
var app = angular.module('plunker', []);
app.controller('MainCtrl', function($scope) {
$scope.name = 'World';
$scope.list = [
[{
rodzina: 'This is one',
page: '111'
}, {
rodzina: 'This is two',
page: '222'
}, {
rodzina: 'This is three',
page: '333'
}],
[{
rodzina: 'This is four',
page: '444'
}, {
rodzina: 'This is five',
page: '555'
}, {
rodzina: 'This is six',
page: 666
}],
[{
rodzina: 'This is seven',
page: 777
}, {
rodzina: 'This is eight',
page: '888'
}, {
rodzina: 'This is nine',
page: '999'
}],
]
});
My code is as follows (the fiddle):
<div ng-controller="myCtrl">
<div ng-model="currentTab" ng-init="currentTab='Tab1'"/>
<div ng-init="popovers = [
{ name: 'Popover1',
displayName: 'Pop over with two tabs',
tabs: [
{ name: 'Tab1',
displayName: 'First tab',
description: ['First tab description']
},
{ name: 'Tab2',
displayName: 'Second tab',
description: ['Second tab description']
}
]
}
]"/>
<b>Tabs in popover</b>
<div
class="popover"
ng-repeat="p in popovers"
>
Popover name: {{p.displayName}}
<div ng-repeat="t in p.tabs"
class="tab"
ng-class="currentTab==t.name?'selected':''"
ng-click="currentTab=t.name"
>
{{t.name}}
</div>
<div ng-repeat="t in p.tabs"
class="tabContent"
ng-class="currentTab==t.name?'selected':''"
>
<p>{{t.displayName}}</p>
</div>
</div>
</div>
There is something I don't get which make the code not working perfectly, as the selected class name is never removed as one click on the tab.
When you want to modify a variable of your parent scope from within a ng-repeat you need to use $parent.currentTab.
Updated Fiddle
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' }]
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.