Bagaimana cara memfilter (key, value) dengan ng-repeat di AngularJs?

113

Saya mencoba melakukan sesuatu seperti:

<div ng-controller="TestCtrl">
    <div ng-repeat="(k,v) in items | filter:hasSecurityId">
        {{k}} {{v.pos}}
    </div>
</div>

Bagian AngularJs:

function TestCtrl($scope) 
{
    $scope.items = {
                     'A2F0C7':{'secId':'12345', 'pos':'a20'},
                     'C8B3D1':{'pos':'b10'}
                   };

    $scope.hasSecurityId = function(k,v)
    {
       return v.hasOwnProperty('secId');
    }
}

Tapi entah bagaimana, itu menunjukkan semua item. Bagaimana cara memfilter (key, value)?

Vural
sumber
berikan beberapa contoh data untuk item. Atau beri kami biola;)
Robin Drexler
Ini bukan cara Anda membuat filter, lihat dokumentasi , dan seperti yang dikatakan Robin, harap contohnya.
Yahya KACEM
Saya sudah memberikan contoh lengkap dan saya tahu cara menggunakan filter. Saya hanya bertanya "bagaimana menggunakan filter dengan (key, value)".
Vural
indeks dan hitungan harus tersedia dalam cakupan itu iirc
Shanimal

Jawaban:

131

Filter sudut hanya dapat diterapkan ke array dan bukan objek, dari API sudut -

"Memilih subset item dari array dan mengembalikannya sebagai array baru."

Anda memiliki dua opsi di sini:
1) pindah $scope.itemske array atau -
2) pra-filter ng-repeatitem, seperti ini:

<div ng-repeat="(k,v) in filterSecId(items)">
    {{k}} {{v.pos}}
</div>

Dan di Kontroler:

$scope.filterSecId = function(items) {
    var result = {};
    angular.forEach(items, function(value, key) {
        if (!value.hasOwnProperty('secId')) {
            result[key] = value;
        }
    });
    return result;
}

jsfiddle : http://jsfiddle.net/bmleite/WA2BE/

bmleite
sumber
9
Seseorang perlu berhati-hati dengan pendekatan ini untuk menghindari loop tak terbatas (digest). Lihat 6054 dan 705 . Ringkasan oleh Narretz : Singkatnya, menggunakan fungsi untuk mengembalikan koleksi dalam ng-repeat adalah anti-pola. Lebih baik menetapkan koleksi ke properti cakupan, dan mengulanginya.
Joe23
3
Komentar yang berguna. Ini membuat saya bingung; Saya berharap dapat memfilter iterable apa pun . Terimakasih banyak. :)
Chris Krycho
3
Catatan: Ini adalah pola anti kinerja sekarang. Angular 1.3 memiliki filter stateless sekarang ( egghead.io/lessons/… ) jadi Anda pasti ingin membuat filter untuk ini.
kentcdodds
8
@kentcdodds jangan posting link yang tidak gratis!
Sebastian
11
Mengapa tidak menambahkan ng-if pada elemen berulang?
CarbonDry
45

Solusi saya adalah membuat filter khusus dan menggunakannya:

app.filter('with', function() {
  return function(items, field) {
        var result = {};
        angular.forEach(items, function(value, key) {
            if (!value.hasOwnProperty(field)) {
                result[key] = value;
            }
        });
        return result;
    };
});

Dan di html:

 <div ng-repeat="(k,v) in items | with:'secId'">
        {{k}} {{v.pos}}
 </div>
Valentyn Shybanov
sumber
1
namun, ini akan berulang n * n kali.
maxisam
27

Anda juga dapat menggunakan ng-repeatdengan ng-if:

<div ng-repeat="(key, value) in order" ng-if="value > 0">
DenisKolodin
sumber
2
Pintar. Ini menghemat banyak waktu.
Safwan
21

Atau cukup gunakan

ng-show="v.hasOwnProperty('secId')"

Lihat solusi terbaru di sini:

http://jsfiddle.net/RFontana/WA2BE/93/

Renaud
sumber
1
Terima kasih .. Saya menggunakan ini tapi dengan ng-ifsebaliknya
Zim
11

Anda cukup menggunakan modul angular.filter , dan kemudian Anda dapat memfilter bahkan menurut properti bertingkat.
lihat: jsbin
2 Contoh:

JS:

angular.module('app', ['angular.filter'])
  .controller('MainCtrl', function($scope) {
  //your example data
  $scope.items = { 
    'A2F0C7':{ secId:'12345', pos:'a20' },
    'C8B3D1':{ pos:'b10' }
  };
  //more advantage example
  $scope.nestedItems = { 
    'A2F0C7':{
      details: { secId:'12345', pos:'a20' }
    },
    'C8B3D1':{
      details: { pos:'a20' }
    },
    'F5B3R1': { secId:'12345', pos:'a20' }
  };
});

HTML:

  <b>Example1:</b>
  <p ng-repeat="item in items | toArray: true | pick: 'secId'">
    {{ item.$key }}, {{ item }}
  </p>

  <b>Example2:</b>
  <p ng-repeat="item in nestedItems | toArray: true | pick: 'secId || details.secId' ">
    {{ item.$key }}, {{ item }}
  </p> 
a8m
sumber
21
Anda harus mengungkapkan bahwa angular.filterbukan modul sudut inti dan Anda adalah pembuatnya.
demisx
Sepertinya toArrayfilter sudah tidak ada. Apakah ada penggantinya, karena filterfilter masih tidak memungkinkan adanya benda?
trisis
6

Ini agak terlambat, tetapi saya mencari filter serupa dan berakhir menggunakan sesuatu seperti ini:

<div ng-controller="TestCtrl">
 <div ng-repeat="(k,v) in items | filter:{secId: '!!'}">
   {{k}} {{v.pos}}
 </div>
</div>
ph6
sumber
2
Bagaimana Anda membuat ini bekerja? Ketika saya menggunakan filter dengan objek ng-diulang, saya mendapatkan kesalahan yang diharapkan berdasarkan dokumentasi Angular.
tonestrike
1

Meskipun pertanyaan ini agak lama, saya ingin membagikan solusi saya untuk developer angular 1. Intinya adalah hanya menggunakan kembali filter sudut asli, tetapi secara transparan meneruskan objek apa pun sebagai larik.

app.filter('objectFilter', function ($filter) {
    return function (items, searchToken) {
        // use the original input
        var subject = items;

        if (typeof(items) == 'object' && !Array.isArray(items)) {
            // or use a wrapper array, if we have an object
            subject = [];

            for (var i in items) {
                subject.push(items[i]);
            }
        }

        // finally, apply the original angular filter
        return $filter('filter')(subject, searchToken);
    }
});

gunakan seperti ini:

<div>
    <input ng-model="search" />
</div>
<div ng-repeat="item in test | objectFilter : search">
    {{item | json}}
</div>

di sini adalah plunker

ollix
sumber
0

Saya membuat lebih banyak filter umum yang telah saya gunakan di banyak proyek:

  • object = objek yang perlu difilter
  • field = bidang di dalam objek yang akan kita filter
  • filter = nilai filter yang harus sesuai dengan bidang

HTML:

<input ng-model="customerNameFilter" />
<div ng-repeat="(key, value) in filter(customers, 'customerName', customerNameFilter" >
   <p>Number: {{value.customerNo}}</p>
   <p>Name: {{value.customerName}}</p>
</div>

JS:

  $scope.filter = function(object, field, filter) {
    if (!object) return {};
    if (!filter) return object;

    var filteredObject = {};
    Object.keys(object).forEach(function(key) {
      if (object[key][field] === filter) {
        filteredObject[key] = object[key];
      }
    });

    return filteredObject;
  };
Belgo, Kanada
sumber