कोणीयजेएस में कई मूल्यों (या ऑपरेशन) को कैसे फ़िल्टर किया जाए


135

मैं filterकोणीय में उपयोग करना चाहता हूं और कई मूल्यों के लिए फ़िल्टर करना चाहता हूं, अगर इसमें कोई एक मान है तो इसे प्रदर्शित किया जाना चाहिए।

मेरे पास इस संरचना का उदाहरण है:

एक वस्तु movieजिसके पास संपत्ति है genresऔर मैं उसके लिए फ़िल्टर करना चाहता हूं Actionऔर Comedy

मुझे पता है कि मैं कर सकता हूं filter:({genres: 'Action'} || {genres: 'Comedy'}), लेकिन अगर मैं इसे गतिशील रूप से फ़िल्टर करना चाहता हूं तो मुझे क्या करना चाहिए। उदाहरण के लिएfilter: variableX

मैं कैसे सेट करूँ variableXमें $scope, जब मैं शैलियों मैं फिल्टर करने के लिए है की एक सरणी है?

मैं इसे एक स्ट्रिंग के रूप में बना सकता हूं और फिर कर सकता eval()हूं लेकिन मैं eval () का उपयोग नहीं करना चाहता ...


16
क्या आपको यकीन है कि filter:({genres: 'Action'} || {genres: 'Comedy'})यहां तक कि काम भी करता है? उस में नहीं है angular 1.3.16
23

4
1.4.8 के लिए ही! यह सिर्फ काम नहीं करता ^ ^
एलेक्स

जवाबों:


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>

यहाँ संपादित करें लिंक है: कोणीय फिल्टर बनाना

अद्यतन : यहाँ एक बेला है जिसमें मेरे सुझाव का एक सटीक डेमो है।


तो फिर बाहर में मैं उन मूवी ऑब्जेक्ट्स को वापस करता हूं जिन्हें मैं प्रदर्शित करना चाहता हूं?
जस्टगोशा

खेद है कि मुझे वापस आने में कुछ देर लगी। मैंने एक ठोस उदाहरण के एक बेला के साथ अपना जवाब अपडेट किया।
Xesued

ठीक है, धन्यवाद, इस बीच मैंने खुद को समझ लिया, लेकिन यह निश्चित रूप से बाद में किसी की मदद करेगा :)
JustGoscha

या तो मेरे पास सक्रिय और निष्क्रिय जैसे दो मूल्य हैं तो मैं इस फिल्टर का उपयोग करके कैसे खोज सकता हूं। हम कस्टम फ़िल्टर नहीं बनाना चाहते हैं।
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
चिंताओं को अलग करने के अलावा, क्या कोई कारण (प्रदर्शन वार) है कि इससे बचा जा सकेगा?
सीन लार्किन

1
जावास्क्रिप्ट संस्करण अगर दूसरों को इसकी तलाश है:$scope.filteredMovies = $filter('filter')($scope.movies, $scope.filterByGenres);
इवान

23

एक कस्टम फ़िल्टर बनाना यहां ओवरकिल हो सकता है, आप बस एक कस्टम तुलनित्र में पास कर सकते हैं, यदि आपके पास गुणक मान हैं जैसे:

$scope.selectedGenres = "Action, Drama"; 

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

फिर फ़िल्टर में:

filter:{name:selectedGenres}:containsComparator

1
मेरी बहुत मदद की। धन्यवाद
हिस्टो एनेव

@chrismarx ng-modelवर्णित फ़िल्टर तक लिंक करने के लिए दृश्य फ़ाइल में क्या होगा ? अपने जवाब की सादगी की तरह मैं और यह काम करने की कोशिश कर किंतु निश्चित नहीं है कि मेरे लेबल करने के लिए - (क्षमा करें, अभी भी यहाँ सीखने) <input>के ng-model। :)
ट्विनकाब

- आप इस पढ़ने की जरूरत है 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]}

यहाँ ऊपर "फ़िल्टरमुट्ट" कस्टम फ़िल्टर के कार्यान्वयन के साथ एक बेला उदाहरण है । ::: फिडल उदाहरण :::


1
आपको लगता है कि सही इरादा है, लेकिन आपका उदाहरण उम्मीद के मुताबिक काम नहीं करता है। तालिका में आउटपुट असंगत लगता है।
हल्टनर

यह JSON की नेस्टेड ऑब्जेक्ट्स के साथ काम नहीं करता है। अगर यह किया होता तो आदर्श होता। यह भी length property undefinedकंसोल में एक त्रुटि आग ।
सीनसिंक

यह मेरे लिए काम कर रहा है, लेकिन यह सभी परिणामों को लौटाता है यदि यह सूची में खोजा गया गुण नहीं पाता है, तो मैं इस व्यवहार को उलटने के लिए कैसे कर सकता हूं और यदि मूल्य सूची में मौजूद नहीं है तो कोई परिणाम नहीं लौटाता है?
ज़कारिया बेलघी

@ZakariaBelghiti अगर आप कोई परिणाम नहीं लौटाना चाहते हैं, तो कोड बदलें: if (fData.length > 0){ this.filteredData = fData; } बस: this.filteredData = fData;
pconnor88

@Gerfried मुझे लगता है कि साइट वास्तव में Stackoverflow को स्क्रैप करती है, इसलिए उन्होंने उसका जवाब चुरा लिया, अन्य तरीके से नहीं
क्रिस

13

यदि आप वस्तुओं के ऐरे पर फ़िल्टर करना चाहते हैं तो आप दे सकते हैं

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

व्यक्तिगत संपत्ति को उस संपत्ति के लिए दिए गए विशेष फिल्टर द्वारा फ़िल्टर किया जाएगा।

लेकिन अगर आप अलग-अलग प्रॉपर्टी द्वारा फिल्टर और सभी संपत्तियों के लिए वैश्विक स्तर पर फ़िल्टर करना चाहते हैं तो आप ऐसा कुछ कर सकते हैं।

<tr ng-repeat="supp in $data | filter : filterObject |  filter : search">
जहां "फ़िल्टरऑब्जेक्ट" एक व्यक्ति की संपत्ति की खोज करने के लिए एक वस्तु है और "खोज" विश्व स्तर पर प्रत्येक संपत्ति में खोज करेगा।

~ अतुल


यह मेरे लिए अच्छी तरह से काम करता था और एक फ़ंक्शन के लिए फ़िल्टरिंग को ऑफ़लोड करने का सुझाव देने वाले अन्य लोगों की तुलना में बेहतर समाधान था क्योंकि स्ट्रिंग्स पर फ़िल्टर करने पर AngularJS आंशिक पाठ से मेल खाता है।
स्नेवर

9

मैंने इस पर कुछ समय बिताया है और @chrismarx के लिए धन्यवाद, मैंने देखा कि कोणीय डिफ़ॉल्ट 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 है

नोट: अपेक्षित सरणी में केवल स्ट्रिंग , संख्या जैसी सरल वस्तुएँ होनी चाहिए आदि।


धन्यवाद इससे मुझे मदद मिली। एक एकल मान फ़िल्टर के लिए जाँच करने के लिए WWOOO: {name: 'Jack'} अगर किसी को मेरी जैसी ही ज़रूरत है ...
जुआन

7

आप में से searchField फिल्टर का उपयोग कर सकते angular.filter

जे एस:

$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
आप संग्रह में "कहाँ" का कोणीय.फिल्टर <tr ng-repeat = "obj का भी उपयोग कर सकते हैं। जहाँ: {id: 1}"> {{obj.name}} </ tr>
hcarreras

1
searchयहाँ बंद हो जाता है।
आकाश

1
मैंने यह कोशिश की और अपने कोणीय ऐप में मॉड्यूल और अपने इंडेक्स एचटीएमएल में स्क्रिप्ट दोनों को सेटअप किया, लेकिन मैं अभी भी सभी क्षेत्रों की खोज करने में सक्षम हूं, न कि केवल एक जिसे मैंने निर्दिष्ट किया है :(
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
अच्छा और सरल उपाय!
लियोपोल्डो सान्ज़िक

7

उदाहरण के लिए, सबसे तेज़ समाधान जो मैंने पाया है , उदाहरण के लिए कोणीय-फ़िल्टरfilterBy से फ़िल्टर का उपयोग करना :

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

उलटा वह है कोणीय-फिल्टर एक काफी लोकप्रिय पुस्तकालय (~ गिटहब पर 2.6k सितारे) है जो अभी भी सक्रिय रूप से विकसित और बनाए रखा गया है, इसलिए इसे निर्भरता के रूप में अपनी परियोजना में जोड़ना ठीक होना चाहिए।


1
अब तक का सबसे अच्छा जवाब। धन्यवाद।
डैनियल ग्रुज़्ज़ेक

4

मेरा मानना ​​है कि यह वही है जो आप ढूंढ रहे हैं:

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

1
यह केवल सरणियों को संक्षिप्त करता है और एक संघ वापस नहीं करता है।
मुअज़ज़

जब तक मैं कार्यान्वयन को गलत नहीं मानता मैं यह देखने में विफल रहता हूं कि यह समस्या कैसे है।
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

मेरी भी ऐसी ही स्थिति थी। कस्टम फ़िल्टर लिखना मेरे लिए काम करता है। उम्मीद है की यह मदद करेगा!

जे एस:

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
क्या यह सिर्फ 'कॉमेडी' पर फिल्टर नहीं है?
user1135469

2
मैंने यह कोशिश की और यह केवल 'कॉमेडी' पर फिल्माया गया, 'एक्शन' पर नहीं।
बेन
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.