AngularJS의 여러 특정 모델 속성으로 필터링 (OR 관계)


107

http://docs.angularjs.org/api/ng.filter:filter 에서 예제를 살펴보십시오.

을 사용하여 전화 속성으로 <input ng-model="search">검색 할 수 있으며을 사용하여 이름으로 만 검색 할 수 <input ng-model="search.name">있으며 결과는 이름별로 적절하게 필터링됩니다 (전화 번호를 입력해도 예상대로 결과가 반환되지 않음).

하자 내가, 내가 어떻게에 의해 필터링에 대해 갈 것 "이름"속성,에 "전화"속성, 그리고 "비밀"속성을 가진 모델이 있다고 모두 "전화"속성과 "이름"을 하지 은 "비밀"속성을 ? 따라서 본질적으로 사용자는 이름이나 전화 번호를 입력 할 수 ng-repeat있으며은 올바르게 필터링되지만 사용자가 "비밀"값의 일부와 동일한 값을 입력하더라도 아무것도 반환하지 않습니다.

감사.


허, 입력 필드에 "이름"개체를 추가하면 ng-model( search.nameINPUT 필드에 지정 ng-model) 개체가 name속성에 의해 필터링되는 반복되는 결과가 발생 하는 이유에 대해 정말 혼란 스럽 습니다 . 즉 직관적으로 나에게, 당신은 단지에 의해 구체적으로 필터 할 수 있어야합니다 name당신에 지정하여 ng-repeat필터 : filter: friend.name대신`쓰기`<입력 겨 모델 = "search.name">의 ...
LazerSharks

답변:


171

여기 플런 커가 있습니다

더 깔끔한 코드와 쿼리 및 검색 목록 항목 모두 대소 문자를 구분하지 않는 새로운 플 런커

주요 아이디어는 이러한 목적을 달성하기 위해 필터 기능을 만드는 것입니다.

에서 공식 문서

function : 술어 함수를 사용하여 임의의 필터를 작성할 수 있습니다. 이 함수는 배열의 각 요소에 대해 호출됩니다. 최종 결과는 술어가 true를 리턴 한 요소의 배열입니다.

<input ng-model="query">

<tr ng-repeat="smartphone in smartphones | filter: search "> 

$scope.search = function(item) {
    if (!$scope.query || (item.brand.toLowerCase().indexOf($scope.query) != -1) || (item.model.toLowerCase().indexOf($scope.query.toLowerCase()) != -1) ){
        return true;
    }
    return false;
};

최신 정보

어떤 사람들은 실제 성능에 대한 우려를 가질 수 있습니다.

현실 세계에서는 아마도 컨트롤러에서 이런 종류의 필터를 수행 할 것입니다.

수행 방법을 보여주는 세부 게시물 은 다음과 같습니다 .

간단히 말해, ng-change새로운 검색 변경을 모니터링하기위한 입력에 추가 합니다.

그런 다음 필터 기능을 트리거합니다.


1
안녕하세요 @maxisam, 이중 수직선이 무엇을 의미하는지 설명해 주시겠습니까? 나는이 라인을 읽는 방법을 정말 잘 모르겠어요 :item.brand.indexOf($scope.query)!=-1 || item.model.indexOf($scope.query)!=-1)
LazerSharks

15
|| OR을 의미합니다. 좋은 부분 인 자바 스크립트를 읽고 싶을 것입니다.
maxisam

1
||에 대해 말하자면, 방금 시도해 보았고 작동합니다 : <tr ng-repeat = "스마트 폰의 스마트 폰 | 필터 : 전화 || 이름">. 첫 번째 필터가 우선합니다.
Jazzy 2011

2
@kate angular.lowercase (item.brand) .indexOf ... 기본적으로 모든 것을 소문자로 지정합니다
maxisam

1
@maxisam. 대소 문자를 구분하지 않는 것이 올바르게 작동하려면 쿼리 문자열도 소문자 여야합니다. 여기 에 작업 케이스 무감각을 가진 당신포크가 있습니다 . plnkr.co/edit/auz02bvWm1Vw4eItSa5J?p=preview 필터에 감사드립니다.
Leopold Kristjansson

78

API 참조에 설명 된대로 객체를 매개 변수로 필터 표현식에 전달할 수 있습니다 . 이 개체는 다음과 같이 관심있는 속성을 선택적으로 적용 할 수 있습니다.

<input ng-model="search.name">
<input ng-model="search.phone">
<input ng-model="search.secret">
<tr ng-repeat="user in users | filter:{name: search.name, phone: search.phone}">

여기 플런 커가 있습니다

주의 ...이 예제는 AngularJS 1.1.5에서 잘 작동하지만 항상 1.0.7에서는 잘 작동하지 않습니다. 이 예제에서 1.0.7은 모든 것을 필터링하여 초기화 한 다음 입력 사용을 시작할 때 작동합니다. 공백으로 시작하더라도 입력에 일치하지 않는 값이있는 것처럼 동작합니다. 안정적인 릴리스를 유지하려면 상황에 맞게 시도해보십시오.하지만 일부 시나리오에서는 1.2.0이 릴리스 될 때까지 @maxisam의 솔루션을 사용할 수 있습니다.


26
플 런커를 보면 검색 창이 하나뿐이라면 원하는 효과를 얻을 수있는 방법이 있습니다. 이것이 도전입니다 ... 수술 부위입니다.
silvster27

2
이 대답은 금이지만 질문에 대한 대답은 아닙니다.
Cyril CHAPON 2015 년

1
테이블의이 예와 같이 하나의 입력 필드만으로 어떻게 수행 할 수 있습니까? datatables.net
Flash

게시 된 Plunker에서 필터링 된 데이터의 수를 어떻게 얻을 수 있습니까?
Muhammad Zeeshan Tahir

5

나는 @maxisam의 답변에서 영감을 얻어 내 자신의 정렬 기능을 만들었고 그것을 공유하고 싶지만 (심심해서).

상황은 나는 자동차의 배열을 필터합니다. 필터링 할 선택된 속성은 이름, 연도, 가격 및 km입니다. 부동산 가격과 km는 숫자입니다 (따라서 사용 .toString). 또한 대문자를 제어하고 싶습니다 (따라서 .toLowerCase). 또한 필터 쿼리를 다른 단어로 나눌 수 있기를 원합니다 (예 : 필터 2006 Acura가 주어지면 2006 년과 이름이 일치하는 Acura를 찾습니다).

필터에 전달하는 함수

        var attrs = [car.name.toLowerCase(), car.year, car.price.toString(), car.km.toString()],
            filters = $scope.tableOpts.filter.toLowerCase().split(' '),
            isStringInArray = function (string, array){
                for (var j=0;j<array.length;j++){
                    if (array[j].indexOf(string)!==-1){return true;}
                }
                return false;
            };

        for (var i=0;i<filters.length;i++){
            if (!isStringInArray(filters[i], attrs)){return false;}
        }
        return true;
    };

1
뷰 측면에서이 필터를 Angular에서 어떻게 호출하는지 보여줄 수 있습니까?
twknab



2

여기에는 좋은 해결책이 많이 있지만 이것으로 다른 길을가는 것이 좋습니다. 검색이 가장 중요하고 '비밀'속성이 뷰에서 전혀 사용되지 않는 경우; 이에 대한 나의 접근 방식은 모든 이점과 함께 내장 된 각도 필터를 사용하고 단순히 모델을 새로운 객체 배열에 매핑하는 것입니다.

질문의 예 :

$scope.people = members.map(function(member) { 
                              return { 
                                name: member.name, 
                                phone: member.phone
                              }});

이제 html에서는 일반 필터를 사용하여 이러한 속성을 모두 검색합니다.

<div ng-repeat="member in people | filter: searchString">

1
작은 개체를 처리하는 데이 솔루션이 마음에 들지만 중첩 된 항목이 많은 큰 개체 집합이있는 경우 모든 매핑이 혼란 스럽거나 오류가 발생하기 쉽습니다. 기본 요구 사항에 대한 훌륭한 솔루션을위한 +1 ... 전체가 아닌 몇 개의 속성 만 필터링하는 것이 그렇게 복잡하지 않기를 바랍니다! : / ... 미래에 Angular는 이런 종류의 필터를위한 몇 가지 내장 기능을 추가 할 수 있습니다 ...
twknab

2

angularJs에서 filterBy를 사용하는 매우 간단한 접근 방식

작업 plnkr의 경우이 링크를 따르십시오.

http://plnkr.co/edit/US6xE4h0gD5CEYV0aMDf?p=preview

이것은 특별히 단일 속성을 사용하여 여러 열을 검색하지만 전부는 아닙니다.

<!DOCTYPE html>
<html ng-app="myApp">

  <head>
    <script data-require="angular.js@1.4.1" data-semver="1.4.1" src="https://code.angularjs.org/1.4.1/angular.js"></script>
    <script data-require="angular-filter@0.5.2" data-semver="0.5.2" src="https://cdnjs.cloudflare.com/ajax/libs/angular-filter/0.5.2/angular-filter.js"></script>
    <link rel="stylesheet" href="style.css" />
    <script src="script.js"></script>
  </head>

  <body ng-controller="myCtrl as vm">
  <input type="text" placeholder="enter your search text" ng-model="vm.searchText" />
   <table>
     <tr ng-repeat="row in vm.tableData | filterBy: ['col1','col2']: vm.searchText">
       <td>{{row.col1}}</td>
       <td>{{row.col2}}</td>
       <td>{{row.col3}}</td>
     </tr>
   </table>
   <p>This will show filter from <b>two columns</b> only(col1 and col2) . Not from all. Whatever columns you add into filter array they
   will be searched. all columns will be used by default if you use <b>filter: vm.searchText</b></p>
  </body>
</html>

제어 장치

// Code goes here
(function(){

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

  myApp.controller('myCtrl', function($scope){
    var vm= this;
    vm.x = 20;

    vm.tableData = [
      {
        col1: 'Ashok',
        col2: 'Tewatia',
        col3: '12'
      },{
        col1: 'Babita',
        col2: 'Malik',
        col3: '34'
      },{
        col1: 'Dinesh',
        col2: 'Tewatia',
        col3: '56'
      },{
        col1: 'Sabita',
        col2: 'Malik',
        col3: '78'
      }
      ];
  })

})();

단점은 하나 이상의 타사 플러그인을 추가한다는 것입니다. 부르는 것이 중요합니다.
mix3d

2

나는 이것을 간단히 해결했다.

<div ng-repeat="Object in List | filter: (FilterObj.FilterProperty1 ? {'ObjectProperty1': FilterObj.FilterProperty1} : '') | filter:(FilterObj.FilterProperty2 ? {'ObjectProperty2': FilterObj.FilterProperty2} : '')">

1

http://plnkr.co/edit/A2IG03FLYnEYMpZ5RxEm?p=preview

다음은 각 모델에서도 검색 할 단어로 검색을 구분하는 대소 문자 구분 검색입니다. 공백을 찾은 경우에만 쿼리를 배열로 분할 한 다음 각 단어를 검색합니다.

모든 단어가 모델 중 하나 이상에 있으면 true를 반환합니다.

$scope.songSearch = function (row) {
    var query = angular.lowercase($scope.query);
    if (query.indexOf(" ") > 0) {
        query_array = query.split(" ");
        search_result = false;
        for (x in query_array) {
            query = query_array[x];
            if (angular.lowercase(row.model1).indexOf(query || '') !== -1 || angular.lowercase(row.model2).indexOf(query || '') !== -1 || angular.lowercase(row.model3).indexOf(query || '') !== -1){
                search_result = true;
            } else {
                search_result = false;
                break;
            }
        }
        return search_result;
    } else {
        return (angular.lowercase(row.model1).indexOf(query || '') !== -1 || angular.lowercase(row.model2).indexOf(query || '') !== -1 || angular.lowercase(row.model3).indexOf(query || '') !== -1);
    }
};

1

필터는 필드가있는 JavaScript 객체 일 수 있으며 다음과 같은 표현식을 가질 수 있습니다.

ng-repeat= 'item in list | filter :{property:value}'

0

가능한 한 간단하게 보관하고 싶습니다. 국제별로 그룹화하고 모든 열을 필터링하고 각 그룹의 개수를 표시하고 항목이없는 경우 그룹을 숨겨야했습니다.

또한 나는 이와 같은 단순한 것을 위해 사용자 정의 필터를 추가하고 싶지 않았습니다.

        <tbody>
            <tr ng-show="fusa.length > 0"><td colspan="8"><h3>USA ({{fusa.length}})</h3></td></tr>
            <tr ng-repeat="t in fusa = (usa = (vm.assignmentLookups | filter: {isInternational: false}) | filter: vm.searchResultText)">
                <td>{{$index + 1}}</td>
                <td ng-bind-html="vm.highlight(t.title, vm.searchResultText)"></td>
                <td ng-bind-html="vm.highlight(t.genericName, vm.searchResultText)"></td>
                <td ng-bind-html="vm.highlight(t.mechanismsOfAction, vm.searchResultText)"></td>
                <td ng-bind-html="vm.highlight(t.diseaseStateIndication, vm.searchResultText)"></td>
                <td ng-bind-html="vm.highlight(t.assignedTo, vm.searchResultText)"></td>
                <td ng-bind-html="t.lastPublished | date:'medium'"></td>
            </tr>
        </tbody>
        <tbody>
            <tr ng-show="fint.length > 0"><td colspan="8"><h3>International ({{fint.length}})</h3></td></tr>
            <tr ng-repeat="t in fint = (int = (vm.assignmentLookups | filter: {isInternational: true}) | filter: vm.searchResultText)">
                <td>{{$index + 1}}</td>
                <td ng-bind-html="vm.highlight(t.title, vm.searchResultText)"></td>
                <td ng-bind-html="vm.highlight(t.genericName, vm.searchResultText)"></td>
                <td ng-bind-html="vm.highlight(t.mechanismsOfAction, vm.searchResultText)"></td>
                <td ng-bind-html="vm.highlight(t.diseaseStateIndication, vm.searchResultText)"></td>
                <td ng-bind-html="vm.highlight(t.assignedTo, vm.searchResultText)"></td>
                <td ng-bind-html="t.lastPublished | date:'medium'"></td>
            </tr>
        </tbody>

0

나는 매우 늦을지도 모르지만 이것이 내가 한 일입니다. 저는 매우 일반적인 필터를 만들었습니다.

angular.module('app.filters').filter('fieldFilter', function() {
        return function(input, clause, fields) {
            var out = [];
            if (clause && clause.query && clause.query.length > 0) {
                clause.query = String(clause.query).toLowerCase();
                angular.forEach(input, function(cp) {
                    for (var i = 0; i < fields.length; i++) {
                        var haystack = String(cp[fields[i]]).toLowerCase();
                        if (haystack.indexOf(clause.query) > -1) {
                            out.push(cp);
                            break;
                        }
                    }
                })
            } else {
                angular.forEach(input, function(cp) {
                    out.push(cp);
                })
            }
            return out;
        }

    })

그럼 이렇게 사용하세요

<tr ng-repeat-start="dvs in devices |  fieldFilter:search:['name','device_id']"></tr>

검색 창은 다음과 같습니다.

<input ng-model="search.query" class="form-control material-text-input" type="text">

여기서 name 및 device_id는 dvs의 속성입니다.


-1

다음은 개체에 대한 빠른 필터를 원하는 사용자를위한 간단한 솔루션입니다.

<select>
  <option ng-repeat="card in deck.Cards | filter: {Type: 'Face'}">{{card.Name}}</option>
</select>

배열 필터를 사용하면 필터링하려는 개체를 모방 할 수 있습니다. 위의 경우 다음 클래스가 제대로 작동합니다.

var card = function(name, type) {
  var _name = name;
  var _type = type;

  return {
    Name: _name,
    Type: _type
  };
};

그리고 갑판은 다음과 같이 보일 수 있습니다.

var deck = function() {
  var _cards = [new card('Jack', 'Face'),
                new card('7', 'Numeral')];

  return {
    Cards: _cards
  };
};

개체의 여러 속성을 필터링하려면 쉼표로 필드 이름을 구분하면됩니다.

<select>
  <option ng-repeat="card in deck.Cards | filter: {Type: 'Face', Name: 'Jack'}">{{card.Name}}</option>
</select>

편집 : 다음은 단일 및 다중 속성 필터의 예를 제공하는 작동중인 plnkr입니다.

http://embed.plnkr.co/i0wCx6l1WPYljk57SXzV/


이러한 유형의 검색을 어떻게 구현 하시겠습니까? 테이블의이 예에서는 단어의 일부를 입력하고 스페이스 키를 누르고 열에 다른 단어의 일부를 입력 할 수 있으며 그에 따라 필터링됩니다. datatables.net
Flash

질문을 제대로 처리하지 않으면 내 게시물이 왜 다운 그레이드되었는지 모르겠습니다. 코드를 올바르게 적용하면 작동합니다.

답장을 보내 주셔서 감사합니다. 누가 투표했는지 모르겠지만 계속해서 다시 투표 할 수 있습니다. 그러나이 예에서는 검색 입력 필드가 있고 입력 할 때 필터링되는 링크에있는 것과 유사합니다. 그녀는 내 원래 게시물 someoune도 투표했습니다. stackoverflow.com/questions/42421941/angular-custom-search
Flash

1
텍스트 상자 필터가 어떻게 작동하는지 보여주기 위해 plnkr을 업데이트했습니다. 예상대로 부분 텍스트를 필터링하는 방법을 확인하십시오. 나는 이것이 당신의 연결된 예에 더 가깝다고 믿습니다. 별도의 데이터 조각에 대해 여러 필터가 필요한 경우 다른 질문입니다.

@Rick을 통해 반복되는 객체 내의 모든 속성이 아닌 2 개의 속성 만 필터링하도록 노력하고 있으므로이 예제에 시간을 투자 해 주셔서 감사합니다 ng-repeat. 그러나 귀하의 예는 약간 복잡해 보입니다. 요약 할 수있는 방법이 있습니까? 질문이 본질적으로 선택한 속성 만 필터링 할 수있는 단일 검색 필드를 찾고 있다는 것을 알고 있습니다. 귀하의 예에서는 액면가 이름이나 숫자 중 하나만 필터링하는 것 같습니다. 귀하의 예를 이해하는 데 잘못된 경우 알려주십시오!
twknab
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.