Memfilter menurut Beberapa Properti Model Tertentu di AngularJS (dalam hubungan ATAU)

107

Lihat contohnya di sini: http://docs.angularjs.org/api/ng.filter:filter

Anda dapat mencari berdasarkan salah satu properti telepon dengan menggunakan <input ng-model="search">dan Anda dapat mencari hanya dengan nama dengan menggunakan <input ng-model="search.name">, dan hasilnya disaring dengan tepat berdasarkan nama (mengetik nomor telepon tidak memberikan hasil apa pun, seperti yang diharapkan).

Katakanlah saya memiliki model dengan "nama" properti, "telepon" properti, dan "rahasia" properti, bagaimana aku pergi tentang penyaringan oleh kedua "nama" dan "telepon" properti dan tidak "rahasia" properti ? Jadi pada dasarnya, pengguna dapat mengetik nama atau nomor telepon dan ng-repeatakan memfilter dengan benar, tetapi meskipun pengguna mengetikkan nilai yang sama dengan bagian dari nilai "rahasia", itu tidak akan mengembalikan apa pun.

Terima kasih.

winduptoy
sumber
Huh, saya benar-benar bingung mengapa melampirkan objek "nama" ke bidang masukan ng-model(ditentukan search.namedi bidang INPUT ng-model) akan mengakibatkan objek diulang disaring oleh namepropertinya? Yaitu secara intuitif bagi saya, Anda harus dapat secara khusus memfilter hanya namedengan menentukan dalam ng-repeatfilter Anda filter: friend.name:, daripada `menulis` <input ng-model = "search.name"> ...
LazerSharks

Jawaban:

171

Ini plunkernya

Plunker baru dengan kode yang lebih bersih & di mana kueri dan item daftar pencarian tidak membedakan huruf besar / kecil

Ide utamanya adalah membuat fungsi filter untuk mencapai tujuan ini.

Dari dokumen resmi

Fungsi: Fungsi predikat dapat digunakan untuk menulis filter arbitrer. Fungsi tersebut dipanggil untuk setiap elemen array. Hasil akhirnya adalah larik dari elemen-elemen yang predikatnya dikembalikan benar.

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

Memperbarui

Beberapa orang mungkin memiliki perhatian pada kinerja di dunia nyata, dan itu benar.

Di dunia nyata, kita mungkin akan melakukan filter semacam ini dari pengontrol.

Berikut adalah detail posting yang menunjukkan bagaimana melakukannya.

singkatnya, kami menambahkan ng-changemasukan untuk memantau perubahan pencarian baru

dan kemudian memicu fungsi filter.

maxisam
sumber
1
Hai @maxisam, bisakah Anda menjelaskan arti garis vertikal ganda? Saya tidak begitu yakin bagaimana membaca baris ini:item.brand.indexOf($scope.query)!=-1 || item.model.indexOf($scope.query)!=-1)
LazerSharks
15
|| berarti OR. Anda mungkin ingin membaca Javascript, bagian yang bagus.
maxisam
1
Ngomong-ngomong tentang ||, coba saja ini dan berhasil: <tr ng-repeat = "smartphone di smartphone | filter: phone || name">. Filter pertama diutamakan.
Jazzy
2
@kate angular.lowercase (item.brand) .indexOf ... pada dasarnya, hanya huruf kecil semuanya
maxisam
1
@dimas_jogja String kueri harus menggunakan huruf kecil juga agar ketidaksensitifan huruf besar / kecil berfungsi dengan benar. Ini adalah Fork of you plunker dengan ketidakpekaan kasus kerja. plnkr.co/edit/auz02bvWm1Vw4eItSa5J?p=preview Terima kasih untuk filternya.
Leopold Kristjansson
78

Anda bisa meneruskan Objek sebagai parameter ke ekspresi filter Anda, seperti yang dijelaskan dalam Referensi API . Objek ini dapat secara selektif menerapkan properti yang Anda minati, seperti:

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

Ini Plunker

Perhatian ... contoh ini berfungsi baik dengan AngularJS 1.1.5, tetapi tidak selalu baik di 1.0.7. Dalam contoh ini 1.0.7 akan menginisialisasi dengan semua yang difilter, kemudian bekerja saat Anda mulai menggunakan masukan. Ini berperilaku seperti input memiliki nilai yang tidak cocok di dalamnya, meskipun awalnya kosong. Jika Anda ingin tetap menggunakan rilis stabil, lanjutkan dan coba ini untuk situasi Anda, tetapi beberapa skenario mungkin ingin menggunakan solusi @ maxisam hingga 1.2.0 dirilis.

Anson
sumber
26
Melihat plunker Anda, bagaimana efek yang diinginkan akan tercapai jika Anda hanya memiliki satu kotak pencarian. Ini adalah tantangannya ... bagian OR.
silvster27
2
Jawaban ini emas tapi tidak menjawab pertanyaannya.
Cyril CHAPON
1
Bagaimana Anda melakukannya hanya dengan satu bidang input seperti dalam contoh ini di tabel: datatables.net
Flash
Bagaimana Anda menghitung data yang difilter di Plunker yang diposting?
Muhammad Zeeshan Tahir
5

Saya menginspirasi diri saya sendiri dari jawaban @ maxisam dan membuat fungsi sortir saya sendiri dan saya pikir saya akan membagikannya (karena saya bosan).

Situasi Saya ingin memfilter melalui berbagai mobil. Properti yang dipilih untuk difilter adalah nama, tahun, harga dan km. Harga properti dan km adalah angka (karena itu digunakan .toString). Saya juga ingin mengontrol huruf besar (karenanya .toLowerCase). Juga saya ingin dapat membagi permintaan filter saya menjadi kata-kata yang berbeda (mis. Diberi filter Acura 2006, ia menemukan kecocokan 2006 dengan tahun dan Acura dengan nama).

Fungsi saya lolos ke filter

        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;
    };
NicolasMoise
sumber
1
Bisakah Anda menunjukkan bagaimana, di sisi tampilan, Anda memanggil filter ini di Angular?
twknab
5

Jika Anda terbuka untuk menggunakan pustaka pihak ketiga, 'Filter Angular' dengan koleksi filter yang bagus mungkin berguna:

https://github.com/a8m/angular-filter#filterby

collection | filterBy: [prop, nested.prop, etc..]: search
Khashayar
sumber
3

Semoga jawaban ini bisa membantu, Filter Nilai Ganda

Dan contoh kerja di biola ini

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

Ada banyak solusi bagus di sini tetapi saya sarankan untuk pergi ke rute lain dengan ini. Jika pencarian adalah hal terpenting dan properti 'rahasia' sama sekali tidak digunakan pada tampilan; pendekatan saya untuk ini adalah dengan menggunakan filter bersudut built-in dengan semua manfaatnya dan hanya memetakan model ke array objek baru.

Contoh dari pertanyaan:

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

Sekarang, di html cukup gunakan filter biasa untuk mencari kedua properti ini.

<div ng-repeat="member in people | filter: searchString">
Siddharth Singh
sumber
1
Saya suka solusi ini untuk menangani objek kecil, tetapi jika Anda memiliki sekumpulan besar objek dengan banyak hal bersarang, pemetaan semuanya bisa membingungkan / mudah membuat kesalahan. +1 meskipun untuk solusi hebat untuk kebutuhan dasar ... semoga ini tidak terlalu rumit untuk memfilter hanya beberapa properti saja! : / ... mungkin di masa mendatang Angular dapat menambahkan beberapa fungsi
bawaan
2

Pendekatan cukup lurus ke depan menggunakan filterBy di angularJs

Untuk bekerja, silakan ikuti tautan ini

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

Ini secara khusus menggunakan satu properti untuk mencari di beberapa kolom tetapi tidak semua.

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

  <head>
    <script data-require="[email protected]" data-semver="1.4.1" src="https://code.angularjs.org/1.4.1/angular.js"></script>
    <script data-require="[email protected]" 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>

pengontrol

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

})();
CredibleAshok
sumber
Kelemahannya adalah menambahkan satu plugin pihak ketiga lagi. Penting untuk disinggung.
mix3d
2

Saya menyelesaikan ini dengan sederhana:

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

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

Berikut adalah pencarian case sensitive yang juga memisahkan pencarian Anda menjadi kata-kata untuk dicari di setiap model juga. Hanya ketika menemukan spasi, ia akan mencoba membagi kueri menjadi array dan kemudian mencari setiap kata.

Ini mengembalikan nilai true jika setiap kata setidaknya di salah satu model.

$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);
    }
};
Tom Quinlan
sumber
1

Filter dapat berupa objek JavaScript dengan bidang dan Anda dapat memiliki ekspresi sebagai:

ng-repeat= 'item in list | filter :{property:value}'
Gholamreza Fathpour
sumber
0

Saya ingin tetap sederhana jika memungkinkan. Saya perlu mengelompokkan menurut Internasional, memfilter semua kolom, menampilkan hitungan untuk setiap grup dan menyembunyikan grup jika tidak ada item.

Ditambah saya tidak ingin menambahkan filter kustom hanya untuk sesuatu yang sederhana seperti ini.

        <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>
Louis Rebolloso
sumber
0

Saya mungkin akan sangat terlambat tetapi inilah yang akhirnya saya lakukan. Saya membuat filter yang sangat umum.

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

    })

Kemudian gunakan seperti ini

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

Kotak pencarian Anda akan seperti

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

di mana nama dan device_id adalah properti di dvs

Raj Sharma
sumber
-1

Berikut solusi sederhana bagi mereka yang menginginkan filter cepat terhadap suatu objek:

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

Filter array memungkinkan Anda meniru objek yang Anda coba filter. Dalam kasus di atas, kelas-kelas berikut akan berfungsi dengan baik:

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

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

Dan di mana dek akan terlihat seperti:

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

  return {
    Cards: _cards
  };
};

Dan jika Anda ingin memfilter beberapa properti objek cukup pisahkan nama bidang dengan koma:

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

EDIT: Berikut adalah plnkr yang berfungsi yang memberikan contoh filter properti tunggal dan ganda:

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

Rick
sumber
Bagaimana Anda akan menerapkan jenis pencarian ini? Dalam contoh ini di tabel mereka, Anda dapat mengetik bagian dari sebuah kata, menekan tombol spasi, dan mengetik bagian dari kata lain di kolom, dan masih memfilter yang sesuai. datatables.net
Flash
Saya tidak tahu mengapa posting saya diturunkan kecuali saya tidak menjawab pertanyaan dengan benar. Kode berfungsi jika Anda menerapkannya dengan benar.
Rick
terima kasih atas balasan Anda rick Saya tidak tahu siapa yang menolak tetapi saya dapat melanjutkan dan memberikan suara kembali. Namun dalam contoh itu bagaimana itu mirip dengan yang ada di tautan yang saya berikan di mana mereka memiliki bidang input pencarian dan saat mereka mengetiknya menyaring. Miliknya adalah posting origninal saya someoune telah memilihnya juga: stackoverflow.com/questions/42421941/angular-custom-search
Flash
1
Saya telah memperbarui plnkr untuk menunjukkan cara kerja filter kotak teks. Perhatikan bagaimana filter pada teks parsial seperti yang diharapkan. Saya yakin ini lebih dekat dengan contoh Anda yang ditautkan. Jika Anda membutuhkan beberapa filter (untuk potongan data terpisah) maka itu pertanyaan yang berbeda.
Rick
@Rick Saya sangat menghargai Anda meluangkan waktu untuk contoh ini, karena saat ini saya mencoba mencari tahu diri saya hanya untuk memfilter 2 properti daripada semua properti dalam suatu objek yang diulang melalui ng-repeat. Namun, contoh Anda tampaknya agak rumit: adakah cara untuk meringkasnya? Saya tahu pertanyaannya pada dasarnya adalah mencari satu bidang pencarian yang dapat memfilter properti yang dipilih saja. Dalam contoh Anda, sepertinya kami memfilter nama atau angka nilai nominal, tetapi tidak keduanya. Jika saya salah memahami contoh Anda, beri tahu saya!
twknab