angularJS에서 여러 값을 필터링하는 방법 (또는 연산)


135

사용하고 싶습니다 filter각도 여러 값을 필터링하고 싶습니다. 값 중 하나가 있으면 표시해야합니다.

예를 들어이 구조가 있습니다.

객체 movie속성을 가지고 genres내가 대한 필터링 할 ActionComedy .

할 수는 filter:({genres: 'Action'} || {genres: 'Comedy'})있지만 동적으로 필터링하려면 어떻게해야합니까? 예 :filter: variableX

필터링해야하는 장르 배열이있는 경우 variableX에서 어떻게 설정 $scope합니까?

나는 그것을 문자열로 구성 한 다음 할 수 eval()있지만 eval ()을 사용하고 싶지 않습니다 ...


16
그게 filter:({genres: 'Action'} || {genres: 'Comedy'})효과 가 있다고 확신 합니까? 에 없습니다 angular 1.3.16.
twmulloy 2016 년

4
1.4.8와 동일! 그것은 작동하지 않습니다 ^^
Alex

답변:


87

그냥 사용자 정의 필터를 만들 것입니다. 그들은 그렇게 어렵지 않습니다.

angular.module('myFilters', []).
  filter('bygenre', function() {
    return function(movies,genres) {
      var out = [];
      // Filter logic here, adding matches to the out var.
      return out;
    }
  });

주형:

<h1>Movies</h1>

<div ng-init="movies = [
          {title:'Man on the Moon', genre:'action'},
          {title:'Meet the Robinsons', genre:'family'},
          {title:'Sphere', genre:'action'}
       ];" />
<input type="checkbox" ng-model="genrefilters.action" />Action
<br />
<input type="checkbox" ng-model="genrefilters.family" />Family
<br />{{genrefilters.action}}::{{genrefilters.family}}
<ul>
    <li ng-repeat="movie in movies | bygenre:genrefilters">{{movie.title}}: {{movie.genre}}</li>
</ul>

링크 편집 : 각도 필터 만들기

업데이트 : 여기 내 제안에 대한 정확한 데모 가있는 바이올린 이 있습니다.


그런 다음 밖으로 표시하고 싶은 영화 객체를 반환합니까?
JustGoscha

돌아 오는 데 시간이 좀 걸렸습니다. 구체적인 예를 들어 바이올린으로 대답을 업데이트했습니다.
Xesued

좋아, 덕분에 그 동안 나 자신에서 그것을 생각하지만 :) 도움이 사람이 나중에 장해야합니다
JustGoscha

활성 및 비활성과 같은 두 가지 값이 있으며이 필터를 사용하여 sepately 검색하는 방법은 무엇입니까? 우리는 사용자 정의 필터를 만들고 싶지 않습니다.
VjyV

80

컨트롤러 기능을 사용하여 필터링 할 수 있습니다.

function MoviesCtrl($scope) {

    $scope.movies = [{name:'Shrek', genre:'Comedy'},
                     {name:'Die Hard', genre:'Action'},
                     {name:'The Godfather', genre:'Drama'}];

    $scope.selectedGenres = ['Action','Drama'];

    $scope.filterByGenres = function(movie) {
        return ($scope.selectedGenres.indexOf(movie.genre) !== -1);
    };

}

HTML :

<div ng-controller="MoviesCtrl">
    <ul>
        <li ng-repeat="movie in movies | filter:filterByGenres">
            {{ movie.name }} {{ movie.genre }}
        </li>
    </ul>
</div>

1
우려의 분리 외에 이것을 피할 이유가 있습니까?
Sean Larkin

1
다른 사람들이 찾고 있다면 자바 스크립트 버전 :$scope.filteredMovies = $filter('filter')($scope.movies, $scope.filterByGenres);
Evan

23

다음과 같이 배수 값이있는 경우 사용자 정의 필터를 만드는 것은 너무 과도 할 수 있습니다. 사용자 정의 비교기를 전달하면됩니다.

$scope.selectedGenres = "Action, Drama"; 

$scope.containsComparator = function(expected, actual){  
  return actual.indexOf(expected) > -1;
};

그런 다음 필터에서 :

filter:{name:selectedGenres}:containsComparator

1
많은 도움이되었습니다. 감사합니다
흐리 스토 Enev

@chrismarx ng-model설명 된 필터에 연결하기 위해 뷰 파일에 무엇이 있습니까? 하지만 확실히 내 레이블을하는 방법 당신의 대답의 단순처럼하고 작동려고 - (죄송합니다, 아직 여기 학습) <input>'들 ng-model. :)
twknab

당신은 이것을 읽어야합니다 -docs.angularjs.org/api/ng/filter/filter
chrismarx

18

다음은 값 배열을 사용하여 데이터를 필터링하는 사용자 지정 필터의 구현입니다. 배열 및 단일 키 값을 가진 여러 키 개체를 지원합니다. inangularJS API에서 언급했듯이 AngularJS 필터 Doc 은 단일 값을 가진 다중 키 필터를 지원하지만 아래의 사용자 정의 필터는 angularJS와 동일한 기능을 지원하며 값 배열 및 배열과 단일 키 값 조합을 지원합니다. 아래 코드 스 니펫을 찾으십시오.

myApp.filter('filterMultiple',['$filter',function ($filter) {
return function (items, keyObj) {
    var filterObj = {
        data:items,
        filteredData:[],
        applyFilter : function(obj,key){
            var fData = [];
            if (this.filteredData.length == 0)
                this.filteredData = this.data;
            if (obj){
                var fObj = {};
                if (!angular.isArray(obj)){
                    fObj[key] = obj;
                    fData = fData.concat($filter('filter')(this.filteredData,fObj));
                } else if (angular.isArray(obj)){
                    if (obj.length > 0){
                        for (var i=0;i<obj.length;i++){
                            if (angular.isDefined(obj[i])){
                                fObj[key] = obj[i];
                                fData = fData.concat($filter('filter')(this.filteredData,fObj));    
                            }
                        }

                    }
                }
                if (fData.length > 0){
                    this.filteredData = fData;
                }
            }
        }
    };
    if (keyObj){
        angular.forEach(keyObj,function(obj,key){
            filterObj.applyFilter(obj,key);
        });
    }
    return filterObj.filteredData;
}
}]);

용법:

arrayOfObjectswithKeys | filterMultiple:{key1:['value1','value2','value3',...etc],key2:'value4',key3:[value5,value6,...etc]}

위의 "filterMutiple" 사용자 정의 필터 를 구현 한 바이올린 예제입니다 . ::: 바이올린 예 :::


1
의도가 올바른 것 같지만 예제가 예상대로 작동하지 않는 것 같습니다. 테이블의 출력이 다소 일치하지 않습니다.
Hultner

중첩 된 객체가있는 JSON에서는 작동하지 않습니다. 그랬다면 이상적이었을 것입니다. 또한 length property undefined콘솔에서 오류 가 발생합니다 .
SinSync

그것은 나를 위해 일하고 있지만 목록에서 검색 된 속성을 찾지 못하면 모든 결과를 반환합니다.이 동작을 반전시키고 값이 목록에 없으면 결과를 반환하지 않으려면 어떻게해야합니까?
Zakaria Belghiti

@ZakariaBelghiti 결과를 반환하지 않으려면 코드를 다음과 같이 변경하십시오 if (fData.length > 0){ this.filteredData = fData; } . this.filteredData = fData;
pconnor88

@ Gerfried 나는 사이트가 실제로 Stackoverflow를 긁어 내고 있다고 생각합니다. 그래서 그들은 다른 방법으로가 아니라 그의 대답을 훔쳤습니다.
Chris

13

객체 배열을 필터링하려면 다음을 제공 할 수 있습니다

filter:({genres: 'Action', key :value }.

개별 속성은 해당 속성에 지정된 특정 필터로 필터링됩니다.

그러나 개별 속성별로 필터링하고 모든 속성을 전체적으로 필터링하려면 다음과 같이하십시오.

<tr ng-repeat="supp in $data | filter : filterObject |  filter : search">
여기서 "filterObject"는 개별 속성을 검색하기위한 개체이며 "Search"는 모든 속성에서 전 세계를 검색합니다.

~ 아툴


이것은 나를 위해 잘 작동했으며 AngularJS가 문자열을 필터링 할 때 부분 텍스트 일치를 수행하므로 필터링을 함수에 오프로드하는 것을 제안하는 다른 솔루션보다 더 나은 솔루션이었습니다.
Snaver

9

나는 그것에 시간을 보냈고 @ chrismarx 덕분에 angular의 기본값으로 filterFilter자신의 비교기를 전달할 수 있음을 알았습니다 . 여러 값에 대한 편집 된 비교기는 다음과 같습니다.

  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;
    }
  };

그리고 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);
      };
    });

그런 다음 원하는 곳 어디에서나 사용할 수 있습니다.

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


<ul>
  <li ng-repeat="item in list | filterWithOr:{name:['Jack','Chuck']}">
    {{item.name}}
  </li>
</ul>

마지막으로 plunkr이 있습니다.

참고 : 예상 배열에는 String , Number 등과 같은 간단한 객체 만 포함해야합니다 .


고마워 도움이되었습니다. 단일 값 filterWithOr : {name : 'Jack'}을 확인하려면 누군가 나와 같은 것을 원한다면 ...
Juan

7

angular.filter의 searchField 필터를 사용할 수 있습니다

JS :

$scope.users = [
 { first_name: 'Sharon', last_name: 'Melendez' },
 { first_name: 'Edmundo', last_name: 'Hepler' },
 { first_name: 'Marsha', last_name: 'Letourneau' }
];

HTML :

<input ng-model="search" placeholder="search by full name"/> 
<th ng-repeat="user in users | searchField: 'first_name': 'last_name' | filter: search">
  {{ user.first_name }} {{ user.last_name }}
</th>
<!-- so now you can search by full name -->

3
당신은 또한 사용할 수 있습니다 "여기서"angular.filter의 <TR NG 반복 = "OBJ에서 수집 | 여기서 {ID : 1}"> {{obj.name}} </ TR>
hcarreras

1
search여기에서 멈 춥니 다.
Akash

1
나는 이것을 시도하고 내 각도 앱의 모듈과 인덱스 HTML의 스크립트를 모두 설정했지만 지정한 필드뿐만 아니라 모든 필드를 계속 검색 할 수 있습니다.
twknab

7

ngIf상황이 허용 하는 경우 에도 사용할 수 있습니다 .

<div ng-repeat="p in [
 { name: 'Justin' }, 
 { name: 'Jimi' }, 
 { name: 'Bob' }
 ]" ng-if="['Jimi', 'Bob'].indexOf(e.name) > -1">
 {{ p.name }} is cool
</div>

1
좋고 간단한 해결책!
Leopoldo Sanczyk

7

내가 찾은 가장 빠른 해결책 은 예를 들어 angular-filterfilterBy필터 를 사용하는 것입니다 .

<input type="text" placeholder="Search by name or genre" ng-model="ctrl.search"/>   
<ul>
  <li ng-repeat="movie in ctrl.movies | filterBy: ['name', 'genre']: ctrl.search">
    {{movie.name}} ({{movie.genre}}) - {{movie.rating}}
  </li>
</ul>

은 거꾸로이다 각도-필터 가 미세 종속성으로 프로젝트에 추가해야한다, 그래서 여전히 적극적으로 개발하고 유지 상당히 인기있는 라이브러리 (GitHub의에 ~ 2.6k의 별)입니다.


1
가장 좋은 답변입니다. 감사.
다니엘 Gruszczyk

4

나는 이것이 당신이 찾고있는 것이라고 믿습니다.

<div>{{ (collection | fitler1:args) + (collection | filter2:args) }}</div>

1
배열을 연결하고 공용체를 반환하지 않습니다.
muaaz

구현을 잘못 이해하지 않으면 그것이 어떻게 문제인지 알지 못합니다.
jKlaus

2

이것을 시도하십시오

var m = angular.module('yourModuleName');
m.filter('advancefilter', ['$filter', function($filter){
    return function(data, text){
        var textArr = text.split(' ');
        angular.forEach(textArr, function(test){
            if(test){
                  data = $filter('filter')(data, test);
            }
        });
        return data;
    }
}]);

2

영화 용과 장르 용의 두 가지 배열이 있다고 가정 해 봅시다.

필터를 다음과 같이 사용하십시오. filter:{genres: genres.type}

여기서 장르는 배열과 유형이며 장르에 대한 가치가 있습니다.


1

나는 이것을 문자열과 기능에 대해 썼다 (질문이 아니라는 것을 알고 그것을 찾았고 여기에 도착했다).

String.prototype.contains = function(str) {
  return this.indexOf(str) != -1;
};

String.prototype.containsAll = function(strArray) {
  for (var i = 0; i < strArray.length; i++) {
    if (!this.contains(strArray[i])) {
      return false;
    }
  }
  return true;
}

app.filter('filterMultiple', function() {
  return function(items, filterDict) {
    return items.filter(function(item) {
      for (filterKey in filterDict) {
        if (filterDict[filterKey] instanceof Array) {
          if (!item[filterKey].containsAll(filterDict[filterKey])) {
            return false;
          }
        } else {
          if (!item[filterKey].contains(filterDict[filterKey])) {
            return false;
          }
        }
      }
      return true;
    });  
  };
});

용법:

<li ng-repeat="x in array | filterMultiple:{key1: value1, key2:[value21, value22]}">{{x.name}}</li>


1

나는 비슷한 상황이 있었다. 맞춤 필터를 작성하는 것이 나에게 효과적이었습니다. 도움이 되었기를 바랍니다!

JS :

App.filter('searchMovies', function() {
    return function (items, letter) {
        var resulsts = [];
        var itemMatch = new RegExp(letter, 'i');
        for (var i = 0; i < items.length; i++) {
            var item = items[i];
            if ( itemMatch.test(item.name) || itemMatch.test(item.genre)) {
                results.push(item);
            }
        }
        return results;
    };
});

HTML :

<div ng-controller="MoviesCtrl">
    <ul>
        <li ng-repeat="movie in movies | searchMovies:filterByGenres">
            {{ movie.name }} {{ movie.genre }}
        </li>
    </ul>
</div>

1

다음은 테이블 jsfiddle에 대한 필터 및 지시문을 작성하는 방법에 대한 예입니다.

지시문 가져 오기 목록 (데이터) 및 필터를 사용하여 테이블 작성

<div ng-app="autoDrops" ng-controller="HomeController">
<div class="row">
    <div class="col-md-12">
        <h1>{{title}}</h1>
        <ng-Multiselect array-List="datas"></ng-Multiselect>
    </div>
</div>
</div>

내가 당신을 도울 경우 내 기쁨


1

파티에 참여하기에는 너무 늦었지만 누군가를 도울 수 있습니다.

먼저 첫 번째 속성으로 필터링 한 다음 두 번째 필터로 연결하는 두 단계로 수행 할 수 있습니다.

$scope.filterd = $filter('filter')($scope.empList, { dept: "account" });
$scope.filterd = $scope.filterd.concat($filter('filter')($scope.empList, { dept: "sales" }));  

다중 속성 필터가있는 작동 바이올린보기


0

옵션 1 : 각도 제공 필터 비교기 매개 변수 사용

// declaring a comparator method
$scope.filterBy = function(actual, expected) {
    return _.contains(expected, actual); // uses underscore library contains method
};

var employees = [{name: 'a'}, {name: 'b'}, {name: 'c'}, {name: 'd'}];

// filter employees with name matching with either 'a' or 'c'
var filteredEmployees = $filter('filter')(employees, {name: ['a','c']}, $scope.filterBy);

옵션 2 : 각도 제공 필터 부정 사용

var employees = [{name: 'a'}, {name: 'b'}, {name: 'c'}, {name: 'd'}];

// filter employees with name matching with either 'a' or 'c'
var filteredEmployees = $filter('filter')($filter('filter')(employees, {name: '!d'}), {name: '!b'});


-15

가장 좋은 대답은 다음과 같습니다.

filter:({genres: 'Action', genres: 'Comedy'}

5
이것은 단지 'Comedy'를 필터링하지 않습니까?
user1135469

2
나는 이것을 시도했고 'Action'이 아닌 'Comedy'에 대해서만 필터링합니다.
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.