I want to filter object inside nested ng-repeat.
HTML:
<div ng-controller="MyController">
<input type="text" ng-model="selectedCityId" />
<ul>
<li ng-repeat="shop in shops">
<p ng-repeat = "locations in shop.locations | filter:search" style="display: block">
City id: {{ locations.city_id }}
<span style="padding-left: 20px; display: block;" ng-repeat="detail in locations.details | filter:item">Pin code: {{detail.pin}}</span>
</p>
</li>
</ul>
Controller:
var myApp = angular.module('myApp', []);
myApp.controller('MyController', function ($scope) {
$scope.search = function (location) {
if ($scope.selectedCityId === undefined || $scope.selectedCityId.length === 0) {
return true;
}
if (location.city_id === parseInt($scope.selectedCityId)) {
return true;
}
};
$scope.item = function (detail) {
if ($scope.selectedCityId === undefined || $scope.selectedCityId.length === 0) {
return true;
}
if (detail.pin == parseInt($scope.selectedCityId)) {
return true;
}
};
$scope.shops =
[
{
"category_id":2,
"locations":[
{
"city_id":368,
"details": [{
"pin": 627718,
"state": 'MH'
}]
}
]
},
{
"name":"xxx",
"category_id":1,
"locations":[
{
"city_id":400,
"region_id":4,
"details": [{
"pin": 627009,
"state": 'MH'
},{
"pin": 129818,
"state": 'QA'
}]
},
]
},
];
});
Here's the fiddle:
http://jsfiddle.net/suCWn/210/
I want to use multiple filter inside ng-repeat.
Example: Whenever user enters the ID in the input box. The list should filter based on cityID or PinCode. if user enter '129818' it should show pin code result of 129818 along with its parent cityID Similarly, if a user enter 400, the list should filter and show cityID result with 400 along with its child pin code.
EDIT:
Update Code http://codepen.io/chiragshah_mb/pen/aZorMe?editors=1010]
First, you must not filter locations with matching details. Use something like this in the search
filter:
$scope.search = function (location) {
var id = parseInt($scope.selectedCityId);
return isNaN(id) || location.city_id === id ||
location.details.some(function(d) { return d.pin === id });
};
To show details if filtered by cityID, you have to find the parent location
and check if it was filtered.
$scope.item = function (detail) {
var id = parseInt($scope.selectedCityId);
return isNaN(id) || detail.pin === id || locationMatches(detail, id);
};
function locationMatches(detail, id) {
var location = locationByDetail(detail);
return location && location.city_id === id;
}
function locationByDetail(detail) {
var shops = $scope.shops;
for(var iS = 0, eS = shops.length; iS != eS; iS++) {
for(var iL = 0, eL = shops[iS].locations.length; iL != eL; iL++) {
if (shops[iS].locations[iL].details.indexOf(detail) >= 0) {
return shops[iS].locations[iL];
}
}
}
}
EDIT Another, more flexible solution would be to remove all the filters from ngRepeats and do the filtering in a method that you call on ngChange of the search text. Here is the basic structure for this approach.
myApp.controller('MyController', function($scope, $http) {
var defaultMenu = [];
$scope.currentMenu = [];
$scope.searchText = '';
$http.get(/*...*/).then(function (menu) { defaultMenu = menu; } );
$scope.onSearch = function() {
if (!$scope.searchText) {
$scope.currentMenu = defaultMenu ;
}
else {
// do your special filter logic here...
}
};
});
And the template:
<input type="text" ng-model="searchText" ng-change="onSearch()" />
<ul>
<li ng-repeat="category in currentMenu">
...
</li>
</ul>
I have updated your filters. The problem is in your search
filter you are only checking for the city_id, what you should do is:
pid
of a child detail of given locationSimilar thing for the item
filter:
pid
of the detail being filteredcity_id
of the parent location of the detail passed inHere is a working jsFiddle. I hope this helps.
By simply modifying the JSON
to include the city_id
for children so you don't need to loop through it to get the parent's city_id
, the solution is as easy as this:
var myApp = angular.module('myApp', []);
myApp.controller('MyController', function ($scope) {
$scope.search = function (location) {
if (!$scope.selectedCityId)
return true;
//if user's input is contained within a city's id
if (location.city_id.toString().indexOf($scope.selectedCityId) > -1)
return true;
for (var i = 0; i < location.details.length; i++)
//if user's input is contained within a city's pin
if (location.details[i].pin.toString().indexOf($scope.selectedCityId) > -1)
return true;
};
$scope.item = function (detail) {
if (!$scope.selectedCityId)
return true;
//if user's input is contained within a city's id
if (detail.city_id.toString().indexOf($scope.selectedCityId) > -1)
return true;
//if user's input is contained within a city's pin
if (detail.pin.toString().indexOf($scope.selectedCityId) > -1)
return true;
};
Modified JSON
$scope.shops=[{"category_id":2,"locations":[{"city_id":368,"details":[{"city_id":368,"pin":627718,"state":'MH'}]}]},{"name":"xxx","category_id":1,"locations":[{"city_id":400,"region_id":4,"details":[{"city_id":400,"pin":627009,"state":'MH'},{"city_id":400,"pin":129818,"state":'QA'}]},]},];});
If directly modifying the JSON
is not possible, you can modify it like this in this controller directly after this $scope.shops = ...json...
statement:
for(var i=0; i<$scope.shops.length; i++)
for(var j=0, cat=$scope.shops[i]; j<cat.locations.length; j++)
for(var k=0, loc=cat.locations[j]; k<loc.details.length; k++)
loc.details[k].city_id=loc.city_id;
Working fiddle: http://jsfiddle.net/87e314a0/
I tried to make the solution easier to understand :
index.html :
<div ng-controller="MyController">
<input type="text" ng-model="search.city_id" />
<ul>
<li ng-repeat="shop in shops">
<p ng-repeat = "locations in shop.locations | filter:search.city_id" style="display: block">
City id: {{ locations.city_id }}
<span style="padding-left: 20px; display: block;" ng-repeat="detail in locations.details | filter:item">Pin code: {{detail.pin}}</span>
</p>
</li>
</ul>
</div>
app.js :
var myApp = angular.module('myApp', []);
myApp.controller('MyController', function ($scope) {
$scope.shops =
[
{
"category_id":2,
"locations":[
{
"city_id":368,
"details": [{
"pin": 627718,
"state": 'MH'
}]
}
]
},
{
"name":"xxx",
"category_id":1,
"locations":[
{
"city_id":400,
"region_id":4,
"details": [{
"pin": 627009,
"state": 'MH'
},{
"pin": 129818,
"state": 'QA'
}]
},
]
},
];
});
Here's the fiddle : mySolution
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With