How to filter multiple values (OR operation) in angularJS

前端 未结 20 916
清酒与你
清酒与你 2020-11-22 10:01

I want to use the filter in angular and want to filter for multiple values, if it has either one of the values then it should be displayed.

I have for

20条回答
  •  情话喂你
    2020-11-22 10:23

    I've spent some time on it and thanks to @chrismarx, I saw that angular's default filterFilter allows you to pass your own comparator. Here's the edited comparator for multiple values:

      function hasCustomToString(obj) {
            return angular.isFunction(obj.toString) && obj.toString !== Object.prototype.toString;
      }
      var comparator = function (actual, expected) {
        if (angular.isUndefined(actual)) {
          // No substring matching against `undefined`
          return false;
        }
        if ((actual === null) || (expected === null)) {
          // No substring matching against `null`; only match against `null`
          return actual === expected;
        }
        // I edited this to check if not array
        if ((angular.isObject(expected) && !angular.isArray(expected)) || (angular.isObject(actual) && !hasCustomToString(actual))) {
          // Should not compare primitives against objects, unless they have custom `toString` method
          return false;
        }
        // This is where magic happens
        actual = angular.lowercase('' + actual);
        if (angular.isArray(expected)) {
          var match = false;
          expected.forEach(function (e) {
            e = angular.lowercase('' + e);
            if (actual.indexOf(e) !== -1) {
              match = true;
            }
          });
          return match;
        } else {
          expected = angular.lowercase('' + expected);
          return actual.indexOf(expected) !== -1;
        }
      };
    

    And if we want to make a custom filter for DRY:

    angular.module('myApp')
        .filter('filterWithOr', function ($filter) {
          var comparator = function (actual, expected) {
            if (angular.isUndefined(actual)) {
              // No substring matching against `undefined`
              return false;
            }
            if ((actual === null) || (expected === null)) {
              // No substring matching against `null`; only match against `null`
              return actual === expected;
            }
            if ((angular.isObject(expected) && !angular.isArray(expected)) || (angular.isObject(actual) && !hasCustomToString(actual))) {
              // Should not compare primitives against objects, unless they have custom `toString` method
              return false;
            }
            console.log('ACTUAL EXPECTED')
            console.log(actual)
            console.log(expected)
    
            actual = angular.lowercase('' + actual);
            if (angular.isArray(expected)) {
              var match = false;
              expected.forEach(function (e) {
                console.log('forEach')
                console.log(e)
                e = angular.lowercase('' + e);
                if (actual.indexOf(e) !== -1) {
                  match = true;
                }
              });
              return match;
            } else {
              expected = angular.lowercase('' + expected);
              return actual.indexOf(expected) !== -1;
            }
          };
          return function (array, expression) {
            return $filter('filter')(array, expression, comparator);
          };
        });
    

    And then we can use it anywhere we want:

    $scope.list=[
      {name:'Jack Bauer'},
      {name:'Chuck Norris'},
      {name:'Superman'},
      {name:'Batman'},
      {name:'Spiderman'},
      {name:'Hulk'}
    ];
    
    
    
    • {{item.name}}

    Finally here's a plunkr.

    Note: Expected array should only contain simple objects like String, Number etc.

提交回复
热议问题