9

I have in angular nested object like this. is there way how to filter it for nested property

<li ng-repeat="shop in shops | filter:search">
search.locations.city_id = 22

I'm showing only parent element but want to filter by both of it, like:

search = 
  category_id: 2
  locations:
    city_id: 368

[
 name: "xxx"
 category_id: 1
 locations: [
   city_id: 368
   region_id: 4
  ,
   city_id: 368
   region_id: 4
  ,
   city_id: 368
   region_id: 4
  ]
,
 name: "xxx"
 category_id: 2
 locations: [
   city_id: 30
   region_id: 4
  ,
   city_id: 22
   region_id: 2
  ]
]

3 Answers 3

28

You also can filter like this (version 1.2.13+)

<li ng-repeat="shop in shops | filter: { locations: [{ city_id: search.locations.city_id }] }">
Sign up to request clarification or add additional context in comments.

4 Comments

well this is working, but by default results are not shown only after input. jsfiddle.net/suCWn/12
@zajca you can workaround by assigning model a value in the controller: $scope.selectedCityId = ''. That has the effect of loading all items before manually changing input
Please be aware of the fact that standard filter compares values as strings matching them from beginning. If you request city_id 1 it will return shops located in cities with ids 10, 15, or 12345. Also it will search only in first object in array, To avoid this you will need to write your own comparator or filter. See example: plnkr.co/edit/Jirxxi
-1: @Envek's comment that "it will search only in first object in array" stands to be emphasized. Using the fiddle you gave, the OP's example search term (city_id = 22) doesn't find a result, although the object with category_id = 2 has a location with that property value.
10

Yes, you can, if I understood your example properly.

Depending on the size of your collection it may be better to compute the collection you iterate over in ng-repeat so that the filter isn't doing it constantly as the model changes.

http://jsfiddle.net/suCWn/

Basically you do something like this, if I understood you correctly:

$scope.search = function (shop) {

    if ($scope.selectedCityId === undefined || $scope.selectedCityId.length === 0) {
        return true;
    }

    var found = false;
    angular.forEach(shop.locations, function (location) {          
        if (location.city_id === parseInt($scope.selectedCityId)) {
            found = true;
        }
    });

    return found;
};

Comments

0

Updated "Words Like Jared" answer to use regular expressions to check if it contains the searchterm. This way starts filtering when you type in 1 number so you don't have to match the entire word

JSfiddle

    angular.forEach(shop.locations, function (location) {          
        if (checknum(location.city_id)) {
            found = true;
        }
    });

    function checknum(num){
        var regx = new RegExp($scope.selectedCityId);
        return regx.test(num);
    };

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.