Search code examples
javascriptangularjshtmlangularjs-filter

angularjs custom filter to check for values inside a data array


I have two filters which filter the data according to the queue key in the data. Here is my code :

var app = angular.module('app', []);

app.controller('mainController', function($scope) {
  // Data object
  $scope.servers = [{
      name: 'ServerA',
      queue: '111'
    },
    {
      name: 'Server7',
      queue: '111'
    },
    {
      name: 'Server2',
      queue: '456'
    },
    {
      name: 'ServerB',
      queue: '456'
    },
  ];

  // Filter defaults
  $scope.Filter = new Object();
  $scope.Filter.queue = {
    'PAV': '111',
    'UAT': '456'
  };

});

// Global search filter
app.filter('searchFilter', function($filter) {
  return function(items, searchfilter) {
    var isSearchFilterEmpty = true;
    angular.forEach(searchfilter, function(searchstring) {
      if (searchstring != null && searchstring != "") {
        isSearchFilterEmpty = false;
      }
    });
    if (!isSearchFilterEmpty) {
      var result = [];
      angular.forEach(items, function(item) {
        var isFound = false;
        angular.forEach(item, function(term, key) {
          if (term != null && !isFound) {
            term = term.toString();
            term = term.toLowerCase();
            angular.forEach(searchfilter, function(searchstring) {
              searchstring = searchstring.toLowerCase();
              if (searchstring != "" && term.indexOf(searchstring) != -1 && !isFound) {
                result.push(item);
                isFound = true;
              }
            });
          }
        });
      });
      return result;
    } else {
      return items;
    }
  }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.7.3/angular.min.js"></script>
<div ng-app="app">
  <div ng-controller="mainController">
    <label>show 111</label>
    <input type="checkbox" ng-model="Filter.queue.PAV" ng-true-value='"111"' ng-false-value='"!111"' />&nbsp;
    <label>show 456</label>
    <input type="checkbox" ng-model="Filter.queue.UAT" ng-true-value='"456"' ng-false-value='"!456"' />&nbsp;

    <hr />

    <table width="100%" cellpadding="5">
      <tr>
        <th>Name</th>

        <th>Queue</th>

      </tr>
      <tr ng-repeat="server in servers | searchFilter:Filter.queue">
        <td>{{server.name}}</td>

        <td>{{server.queue}}</td>

      </tr>
    </table>
  </div>
</div>

the filters work perfectly.

But if I have the data like this where the queue is inside an array:

$scope.servers = [
    {name:'ServerA', queuearr:[{'queue' :'111'}]},
    {name:'Server7', queuearr:[{'queue' :'111'}]},
    {name:'Server2', queuearr:[{'queue' :'456'}]},
    {name:'ServerB', queuearr:[{'queue' :'456'}]},
];

note : there can be multiple objects in the queuerr like this:[{queue :'111'},{queue :'278'}]

How do I alter my current code so that the control goes inside the queuerr array and match the queue and return the result accordingly?


Solution

  • you have some conditions to change in the Angular.forEach take a look at the solution.

    ServerB shows up in both searchs

    var app = angular.module('app', []);
    
    app.controller('mainController', function($scope) {
      // Data object
      $scope.servers = [{
          name: 'ServerA',
          queue: '111'
        },
        {
          name: 'Server7',
          queue: '111'
        },
        {
          name: 'Server2',
          queue: '456'
        },
        {
          name: 'ServerB',
          queue: '456',
          queuearr: [{
            queue: '456'
          }, {
            queue: '111'
          }]
        },
      ];
    
      // Filter defaults
      $scope.Filter = new Object();
      $scope.Filter.queue = {
        'PAV': '111',
        'UAT': '456'
      };
    
    });
    
    // Global search filter
    app.filter('searchFilter', function($filter) {
      return function(items, searchfilter) {
        var isSearchFilterEmpty = true;
        angular.forEach(searchfilter, function(searchstring) {
          if (searchstring != null && searchstring != "") {
            isSearchFilterEmpty = false;
          }
        });
        if (!isSearchFilterEmpty) {
          var result = [];
          angular.forEach(items, function(item) {
            var isFound = false;
            angular.forEach(item, function(term, key) {
              // change here to check for arrays
              if (term || Array.isArray(term) && !isFound) {
                // use JSON.stringify here
                term = JSON.stringify(term);
                term = term.toLowerCase();
                angular.forEach(searchfilter, function(searchstring) {
                  searchstring = searchstring.toLowerCase();
    
                  if (searchstring != "" && term.indexOf(searchstring) != -1 && !isFound) {
                    result.push(item);
                    isFound = true;
                  }
                });
              }
            });
          });
          return result;
        } else {
          return items;
        }
      }
    });
    <script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.7.3/angular.min.js"></script>
    <div ng-app="app">
      <div ng-controller="mainController">
        <label>show 111</label>
        <input type="checkbox" ng-model="Filter.queue.PAV" ng-true-value='"111"' ng-false-value='"!111"' />&nbsp;
        <label>show 456</label>
        <input type="checkbox" ng-model="Filter.queue.UAT" ng-true-value='"456"' ng-false-value='"!456"' />&nbsp;
    
        <hr />
    
        <table width="100%" cellpadding="5">
          <tr>
            <th>Name</th>
    
            <th>Queue</th>
    
          </tr>
          <tr ng-repeat="server in servers | searchFilter:Filter.queue">
            <td>{{server.name}}</td>
    
            <td>{{server.queue}}</td>
    
          </tr>
        </table>
      </div>
    </div>