Search code examples
javascriptangularjsfilterangularjs-filter

Angularjs: ng-repeat filter object within array of objects


I have created a plunker which explains what I am trying to achieve. http://plnkr.co/edit/XAghimH20qwxQGjO42gP?p=preview

I have this array of objects $scope.menus

    $scope.menus = [
          {   
            name: 'Access',
            submenu: [
              { name: 'User List'},
            ]
          },
          {
            name: 'Organization',
            submenu: [
              { name: 'City List'}, 
              { name: 'State List'},
              { name: 'Country List'},
            ]
          },
{
            name: 'Upload Logs',
            submenu: [
                { name: 'Inventory Uploads'},
            ]
        },
        {
            name: 'Bulk Logs',
            submenu: [
                { name: 'Bulk Renewals'},
            ]
        },
        ];

For the outside menu when searched, for eg like Access or Organization, only the searched item is returned.

But when inside menu is searched, for eg like City List, in result I get all the other objects also including City List. I was expecting to get only City List.

I have observed that for a nested array of objects, the filter is not working.

I may be wrong. Please guide me learning something new.

UPDATE @Vivek solution worked. But now I am facing another issue. I have added some other arrays to my existing array.
As I type Bulk or upload in the search field, the submenu appears. But as soon as I typing the second word (for eg Bulk logs or upload logs), the submenu disappears.

If it had appeared when first word was typed, why did it disappeared when the second word was type.Why is it happening?

UPDATE Thank you all for your time and responses.


Solution

  • Filter is only applied to the first loop, you need to add the filter on the submenu ng-repeat like this:

    <html>
      <head>
        <title>AngularJS ng-repeat filter</title>
        <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.9/angular.js"></script>
        <script src="script.js"></script>
        <link rel="stylesheet" type="text/css" href="style.css">
      </head>
    
      <body ng-app="app">
    
      <div ng-controller="democontroller">
    
          <input type="text" placeholder="Search text" ng-model="menuSearch">
          <ul>
            <li ng-repeat="menu in menus | filter : menuSearch">
                <span href="#">{{menu.name}}</span>
                <ul>
                    <li ng-repeat="submenu in menu.submenu | filter: menuSearch"> <!--Notice filter added here-->
                        <a href="#">{{submenu.name}}</a>
                    </li>
                </ul>
            </li>
          </ul>
    
        </div>
    
      </body>
    </html>
    

    For your updated usecase, this might help, basically there is filter on the submenu, but the main menu is showed if the submenu is active or the search contains any of the text from menu:

    <html>
      <head>
        <title>AngularJS ng-repeat filter</title>
        <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.9/angular.js"></script>
        <script src="script.js"></script>
        <link rel="stylesheet" type="text/css" href="style.css">
      </head>
    
      <body ng-app="app">
    
      <div ng-controller="democontroller">
    
          <input type="text" placeholder="Search text" ng-model="menuSearch">
          <ul>
            <li ng-repeat="menu in menus"  ng-if="(menu.submenu | filter: menuSearch).length > 0  || (menu.name.includes(menuSearch))">
                <span href="#">{{menu.name}}</span>
                <ul>
                    <li ng-repeat="submenu in menu.submenu | filter : menuSearch">
                        <a href="#">{{submenu.name}}</a>
                    </li>
                </ul>
            </li>
          </ul>
    
        </div>
    
      </body>
    </html>