1

This is going to be a rather longwinded question, so please bear with me...

I have an array of about 25-30 items. They are sorted through various filters such as brand, type, material, size, etc.. How can I go about building a searchable filter. All of the ones I've seen just include a filter:query | in their filters. However I can't get mine to query my existing array.

Here is what my array looks like, only going to show 1 item to keep size down..

$scope.products = [
{
src: 'images/img/image1.jpg',
name:  'XXX-1A',
brand: 'Brand A',
material: 'dry',
size: '00',
type: 'dry pipe',
color:'red'
}];

Function for filtering (only included 1 to save space):

$scope.brandIncludes = [];

    $scope.includeBrand = function(brand) {
        var i = $.inArray(brand, $scope.brandIncludes);
        if (i > -1) {
            $scope.brandIncludes.splice(i, 1);
        } else {
            $scope.brandIncludes.push(brand);
        }
    }

    $scope.brandFilter = function(products) {
        if ($scope.brandIncludes.length > 0) {
            if ($.inArray(products.brand, $scope.brandIncludes) < 0)
                return;
        }

        return true;
    }

This is what I am using to filter from the HTML, I am using checkboxes to select each filter:

<div class="info" ng-repeat="p in products |  
filter:brandFilter | 
filter:materialFilter | 
filter:typeFilter | 
filter:styleFilter">
</div>

My search bar mark up:

  <div class="filtering">
    <div class="search-sect">
     <input name="dbQuery" type="text" placeholder="Search pieces" class="search-input" ng-model="query"/>
  </div>

One of the filter's mark up:

<input type="checkbox" ng-click="includeStyle('adaptor')"/>Adaptor<br>

Now that you have all the code, here are some of the things I've tried that don't seem to be running right:

My Attempt:

Search bar:

  <input type="text" id="query" ng-model="query"/>

Filter:

<li ng-repeat="p in products | filter:query | orderBy: orderList">

I understand that to some experienced with angular, this is a relatively easy task, but I am just learning and can't seem to wrap my head around searching a query. It's probably a simple solution that I am overlooking. This is my first Angular app and I am trying to bite off more than I can chew in order to learn more.

I appreciate all responses, thanks in advance!

As per request: CodePen

2
  • Could you setup a jsfiddle? Commented Mar 6, 2015 at 15:12
  • Certainly, I have the whole thing in a code pen currently, updated it onto my question. Commented Mar 6, 2015 at 15:14

1 Answer 1

1

The simple built-in angular filter is not smart enough to to work with your checkbox design, so try writing a custom filter. You will need to bind the checkboxes you mentioned to variables in your scope, e.g. brandFilterIsEnabled. See the tutorial for writing custom filters. Here is a working example.

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

myApp.controller('ctrl', function ($scope) {
  $scope.items = [{
    name:'foo',
    color:'red'
  },{
    name:'bar',
    color:'blue'
  },{
    name:'baz',
    color:'green'
  }];

  $scope.searchNames = true;
  $scope.searchColors = true;

  $scope.$watch('searchColors', function(){
    $scope.searchKeys = [ $scope.searchNames ? 'name' : null, $scope.searchColors ? 'color' : null ];
  });
  $scope.$watch('searchNames', function(){
    $scope.searchKeys = [ $scope.searchNames ? 'name' : null, $scope.searchColors ? 'color' : null ];
  });
});

myApp.filter('advancedSearch', function($filter) {
  return function(data, keys, query) {
    results = [];
    if( !query ){
      return data;
    } else {
      
       angular.forEach( data, function( obj ){
          var matched = false;
          angular.forEach( keys, function( key ){
             if( obj[key] ){  
                // match values using angular's built-in filter
                if ($filter('filter')([obj[key]], query).length > 0){
                   // don't add objects to results twice if multiple
                   // keys have values that match query
                   if( !matched ) {
                      results.push(obj);
                   }
                   matched = true;
                }
             }
          });
       });
    }
    return results;
  };
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<html ng-app="myApp">
   <div ng-controller="ctrl">
     <input type='checkbox' ng-model='searchNames'>search names</input>
     <input type='checkbox' ng-model='searchColors'>search colors</input>
     <input type='text' ng-model='query'>search objects</input>
     <ul>
        <li ng-repeat="item in items | advancedSearch : searchKeys : query">
         <span style="color:{{item.color}}">{{item.name}}</span>
        </li>
       </ul>
   </div>
</html>

Sign up to request clarification or add additional context in comments.

15 Comments

.... you don't need custom filters ..... write some simple custom filters for this ....huh? One of those is not relevant, surely?
Just to make sure I understand you, the :query in your example is the search option? Followed by checking if previous filters are enabled?
Sorry, rewrote answer quickly. What I meant was, with the addition of the checkboxes enabling and disabling parts of search scope, custom filters will be necessary.
Just realized that I forgot to include the filtering method I was using in JS, edited my question to include this
@user4470749 Correct, query is the value bound to the text field search box. The second input to the filter is the boolean flag telling the filter whether it is enabled or not.
|

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.