AngularJS'de (OR ilişkisinde) Birden Çok Belirli Model Özelliğine Göre Filtreleme


107

Buradaki örneğe bir göz atın: http://docs.angularjs.org/api/ng.filter:filter

Kullanarak telefon özelliklerinden herhangi birine göre <input ng-model="search">arama yapabilir ve kullanarak sadece isme göre arama yapabilirsiniz <input ng-model="search.name">ve sonuçlar ada göre uygun şekilde filtrelenir (bir telefon numarası yazmak, beklendiği gibi herhangi bir sonuç döndürmez).

Diyelim ben, nasıl tarafından filtre uygulamayla ilgili gider bir "isim" mülkü bir "telefon" mülkü ve "gizli" bir özelliğe sahip bir modeli olduğunu varsayalım hem "telefon" özellikleri ve "isim" ve değil "gizli" özelliği ? Dolayısıyla, özünde, kullanıcı bir ad veya telefon numarası yazabilir ve ng-repeatdoğru bir şekilde filtreleyebilir, ancak kullanıcı "gizli" bir değerin bir kısmına eşit bir değer yazsa bile, hiçbir şey döndürmez.

Teşekkürler.


Huh, neden giriş alanlarına bir "isim" nesnesi ng-modeleklemenin ( search.nameGİRİŞ alanlarında belirtmek ng-model) nesnelerin özelliklerine göre filtrelenerek tekrarlanmasına neden olacağı konusunda gerçekten kafam karıştı name? Benim için sezgisel olarak , `` <input ng-model = " nameng-repeatfilter: friend.name
search.name

Yanıtlar:


171

İşte dalgıç

Daha temiz kodlu ve hem sorgu hem de arama listesi öğelerinin büyük / küçük harfe duyarlı olmadığı yeni planlayıcı

Ana fikir, bu amaca ulaşmak için bir filtre işlevi oluşturmaktır.

Gönderen resmi doc

işlev: Bir yüklem işlevi rastgele süzgeçler yazmak için kullanılabilir. İşlev, dizinin her bir öğesi için çağrılır. Nihai sonuç, yüklemin true döndürdüğü bu öğeler dizisidir.

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

Güncelleme

Bazı insanların gerçek dünyadaki performansla ilgili endişeleri olabilir, bu doğru.

Gerçek dünyada, muhtemelen bu tür bir filtreyi denetleyiciden yapardık.

İşte nasıl yapılacağını gösteren ayrıntılı gönderi .

kısaca, ng-changeyeni arama değişikliğini izlemek için girdiye ekliyoruz

ve ardından filtre işlevini tetikleyin.


1
Merhaba @maxisam, çift dikey çizgilerin ne anlama geldiğini açıklayabilir misiniz? Bu satırı nasıl okuyacağımı gerçekten bilmiyorum:item.brand.indexOf($scope.query)!=-1 || item.model.indexOf($scope.query)!=-1)
LazerSharks

15
|| OR anlamına gelir. Javascript'i, iyi kısımlarını okumak isteyebilirsiniz.
maxisam

1
|| demişken, bunu denedim ve işe yaradı: <tr ng-tekrar = "akıllı telefonlarda akıllı telefon | filtre: telefon || isim">. İlk filtre önceliklidir.
Jazzy

2
@kate angular.lowercase (item.brand) .indexOf ... temelde, her şeyi sadece küçük harf
maxisam

1
@maxisam. Büyük / küçük harf duyarlılığının doğru çalışması için sorgu dizesinin de küçük harf olması gerekir. İşte çalışma vakası duyarsızlığı olan bir Çatal sizden . plnkr.co/edit/auz02bvWm1Vw4eItSa5J?p=preview Filtre için teşekkürler.
Leopold Kristjansson

78

API Başvurusu bölümünde açıklandığı gibi, filtre ifadenize parametre olarak bir Nesne iletebilirsiniz . Bu nesne, ilgilendiğiniz özellikleri seçerek uygulayabilir, örneğin:

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

İşte bir Plunker

Dikkat ... Bu örnek AngularJS 1.1.5 ile harika çalışıyor, ancak 1.0.7'de her zaman iyi değil. Bu örnekte 1.0.7, filtrelenen her şeyle başlatılacak, ardından girişleri kullanmaya başladığınızda çalışacaktır. Boş başlasalar bile, girdilerin içinde eşleşmeyen değerler varmış gibi davranır. Kararlı sürümlerde kalmak istiyorsanız, devam edin ve durumunuz için bunu deneyin, ancak bazı senaryolar @ maxisam'ın çözümünü 1.2.0 yayımlanana kadar kullanmak isteyebilir.


26
Sadece bir arama kutunuz olsaydı, istediğiniz etkiye nasıl ulaşılırdı? İşte zorluk bu ... Ameliyathane kısmı.
silvster27

2
Bu cevap altın ama soruya cevap vermiyor.
Cyril CHAPON

1
Tablodaki bu örnekte olduğu gibi tek bir giriş alanıyla bunu nasıl yapardınız: datatables.net
Flash

Yayınlanan Plunker'daki filtrelenmiş verilerin sayısını nasıl elde edersiniz?
Muhammad Zeeshan Tahir

5

@ Maxisam'ın cevabından kendime ilham verdim ve kendi sıralama işlevimi yarattım ve paylaşmayı düşündüm (çünkü sıkıldım).

Durum Bir dizi arabayı filtrelemek istiyorum. Filtrelenecek seçili özellikler ad, yıl, fiyat ve km'dir. Emlak fiyatı ve km sayıdır (dolayısıyla kullanımı .toString). Ayrıca büyük harfleri de kontrol etmek istiyorum (dolayısıyla .toLowerCase). Ayrıca, filtre sorgumu farklı kelimelere bölebilmek istiyorum (örneğin, 2006 Acura filtresi verildiğinde, 2006 yılla ve Acura adıyla eşleşiyor).

Filtreye geçtiğim işlev

        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
Görünüm tarafında, bu filtreyi Angular'da nasıl adlandırdığınızı gösterebilir misiniz?
twknab



2

Burada bir sürü iyi çözüm var ama bununla diğer rotaya gitmenizi öneririm. Arama en önemli şeyse ve 'gizli' özellik görünümde hiç kullanılmıyorsa; buna yönelik yaklaşımım, tüm faydalarıyla birlikte yerleşik açısal filtreyi kullanmak ve modeli yeni bir nesne dizisine eşlemek olacaktır.

Sorudan örnek:

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

Şimdi, html'de bu iki özelliği de aramak için normal filtreyi kullanın.

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

1
Küçük nesnelerle uğraşmak için bu çözümü seviyorum, ancak çok sayıda iç içe geçmiş nesneye sahip büyük bir nesne kümeniz varsa, her şeyi eşleştirmek kafa karıştırıcı / hata yapmak kolay olabilir. +1, temel ihtiyaçlar için harika bir çözüm olsa da ... keşke bunların hepsi yerine sadece birkaç mülk için filtrelemek o kadar karmaşık olmasaydı! : / ... belki gelecekte Angular bu tür filtreler için bazı yerleşik işlevler ekleyebilir ...
twknab

2

FilterBy in angularJs kullanarak oldukça basit yaklaşım

Plnkr çalışmak için bu bağlantıyı izleyin

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

Bu, özellikle birden çok sütunda arama yapmak için tek bir özelliği kullandı ancak hepsini değil.

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

kontrolör

// 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'
      }
      ];
  })

})();

Dezavantajı, bir tane daha 3. parti eklenti eklemesidir. Seslenmek önemli.
mix3d

2

Bunu basitçe çözdüm:

<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

Burada, aramanızı her modelde de aramak için kelimelere ayıran büyük / küçük harfe duyarlı bir arama. Yalnızca bir boşluk bulduğunda sorguyu bir diziye bölmeye ve ardından her kelimeyi aramaya çalışır.

Her kelime modellerden en az birinde yer alıyorsa doğru döndürür.

$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

Filtre, alanları olan bir JavaScript nesnesi olabilir ve aşağıdaki gibi ifadelere sahip olabilirsiniz:

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

0

Mümkün olduğunda basit tutmayı seviyorum. Enternasyonal'e göre gruplandırmam, tüm sütunları filtrelemem, her grup için sayımı görüntülemem ve hiçbir öğe yoksa grubu gizlemem gerekiyordu.

Ayrıca, sadece böyle basit bir şey için özel bir filtre eklemek istemedim.

        <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

Çok geç kalmış olabilirim ama sonunda bunu yapmaya başladım. Çok genel bir filtre yaptım.

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

    })

Öyleyse böyle kullan

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

Arama kutunuz şöyle olacak

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

Burada name ve device_id, dv'lerdeki özelliklerdir


-1

İşte bir nesneye karşı hızlı bir filtre isteyenler için basit bir çözüm:

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

Dizi filtresi, filtrelemeye çalıştığınız nesneyi taklit etmenizi sağlar. Yukarıdaki durumda, aşağıdaki sınıflar gayet iyi çalışacaktır:

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

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

Ve deste nasıl görünebilir:

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

  return {
    Cards: _cards
  };
};

Ve nesnenin birden çok özelliğini filtrelemek istiyorsanız, alan adlarını virgülle ayırmanız yeterlidir:

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

DÜZENLEME: İşte tekli ve çoklu özellik filtrelerinin bir örneğini sağlayan çalışan bir plnkr:

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


Bu tür aramayı nasıl uygularsınız? Bu örnekte, bir kelimenin bir kısmını yazabilir, boşluk tuşuna basabilir ve bir sütuna başka bir kelimenin bir kısmını yazabilirsiniz ve yine de buna göre filtre uygulayabilirsiniz. datatables.net
Flash

Soruyu doğru bir şekilde ele almadığım sürece gönderimin notunun neden düşürüldüğünü bilmiyorum. Kodu doğru uyguladığınızda çalışır.
Rick

Cevabınız için teşekkürler rick Kimin oy verdiğini bilmiyorum ama devam edip tekrar oylayabilirim. Ancak bu örnekte, sağladığım bağlantıdakine nasıl benzer bir arama giriş alanına sahip oldukları ve yazdıklarında filtreler. Onunki benim ilk gönderimdi, someoune'un da oy vermişti: stackoverflow.com/questions/42421941/angular-custom-search
Flash

1
Bir metin kutusu filtresinin nasıl çalışabileceğini göstermek için plnkr'ı güncelledim. Herhangi bir kısmi metni beklendiği gibi nasıl filtrelediğine dikkat edin. Bunun bağlantılı örneğinize daha yakın olduğuna inanıyorum. Birden fazla filtreye ihtiyacınız varsa (ayrı veri parçaları için) o zaman bu farklı bir soru.
Rick

@Rick Bu örneğe zaman ayırdığınız için gerçekten minnettarım, çünkü şu anda kendimi tekrarlanan bir nesnedeki tüm özellikleri değil, yalnızca 2 özelliği filtrelemeye çalışıyorum ng-repeat. Ancak örneğiniz biraz karmaşık görünüyor: onu kısaltmanın bir yolu var mı? Sorunun aslında yalnızca seçili mülkleri filtreleyebilen tek bir arama alanı aradığını biliyorum. Örneğinizde, yüz değeri adlarını veya sayıları filtreliyormuşuz gibi görünüyor, ancak ikisini birden değil. Örneğinizi anlamakta hatalıysam lütfen bana bildirin!
twknab
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.