Search code examples
angularjsangularjs-filter

Custom Filter not firing in angular1


I have two fields in a digest: genres and secondary_genre which are integers.

I have a dropdown fields of genres which returns a value (ng-model = query.genres)

I have tried to create a custom function which will compare genre and secondary genre to query.genre and return if EITHER condition is met. Individually they work fine i.e with filter:{secondary_genre:query.genre) but for the OR condition I need a custom.

The custom filter I have written is called with

<li ng-repeat="film in listOfTitles | customGenreFilter:query.genre">

The filter is

.filter('customGenreFilter', function() {
    return function(data, query) {
        if (data) {
            return data.filter(data.genres == query || data.secondary_genre == query);
        }
        else {
            return [];
        }
    };
});

but it is throwing errors. How can I write this custom filter to return the item if the condition genres = query.genre OR secondary_genre = query.genre.


Solution

  • Your filter is not working because you are not using the .filter() method properly, the method require the argument to be a lambda function in which return whether the item should or not stay in the list. In order to fix your code you have to change the following line:

    return data.filter(data.genres == query || data.secondary_genre == query);
    

    To:

    return data.filter(function(item) {
        return item.genre == query || item.secondary_genre == query
    });
    

    The following example implements a working version of your filter.

    angular.module('myApp', [])
      .component('app', {
        templateUrl: '/app.html',
        controller: App
      })
      .filter('customGenreFilter', CustomGenreFilter);
    
    function App($scope) {
      $scope.query = {
        genre: ''
      };
      $scope.listOfTitles = [
        { title: 'test 1', genre: 'genre1' },
        { title: 'test 2', genre: 'genre2' },
      ];
    }
    
    function CustomGenreFilter() {
      return function(data, query) {
        if (query === '') return data;
        if (data) return data.filter(function(item) {
          return item.genre == query || item.secondary_genre == query
        });
        return [];
      };
    }
    
    angular.element(function() {
      angular.bootstrap(document, ['myApp']);
    });
    <script id="/app.html" type="text/ng-template">
      <select ng-model="query.genre" ng-options="item as item for item in ['', 'genre1', 'genre2']">
      </select>
      <ul>
        <li ng-repeat="film in listOfTitles | customGenreFilter:query.genre">
          {{ film.title }}
        </li>
      </ul>
    </script>
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.0/angular.js"></script>
    <app />