Cara menampilkan panjang data yang diulang-ulang yang difilter

438

Saya memiliki array data yang berisi banyak objek (format JSON). Berikut ini dapat diasumsikan sebagai isi dari array ini:

var data = [
  {
    "name": "Jim",
    "age" : 25
  },
  {
    "name": "Jerry",
    "age": 27
  }
];

Sekarang, saya menampilkan detail ini sebagai:

<div ng-repeat="person in data | filter: query">
</div

Di sini, kueri dimodelkan ke bidang input di mana pengguna dapat membatasi data yang ditampilkan.

Sekarang, saya memiliki lokasi lain di mana saya menampilkan jumlah orang / orang yang sedang ditampilkan, yaitu Showing {{data.length}} Persons

Yang ingin saya lakukan adalah bahwa ketika pengguna mencari seseorang dan data yang ditampilkan difilter berdasarkan permintaan, maka Showing...personsjuga mengubah nilai orang yang ditampilkan saat ini. Tetapi itu tidak terjadi. Itu selalu menampilkan total orang dalam data daripada yang difilter - bagaimana cara saya mendapatkan jumlah data yang difilter?

pengguna109187
sumber

Jawaban:

746

Untuk Angular 1.3+ (kredit ke @Tom)

Gunakan ekspresi alias (Documents: Angular 1.3.0: ngRepeat , gulir ke bawah ke bagian Argumen ):

<div ng-repeat="person in data | filter:query as filtered">
</div>

Untuk Angular sebelum 1.3

Tetapkan hasilnya ke variabel baru (mis. filtered) Dan akses:

<div ng-repeat="person in filtered = (data | filter: query)">
</div>

Tampilkan jumlah hasil:

Showing {{filtered.length}} Persons

Fiddle contoh serupa . Kredit diberikan ke Pawel Kozlowski

Wah
sumber
42
Ini adalah jawaban sederhana yang tidak mengulangi eksekusi filter.
agmin
3
@ Ben: Ya. Anda dapat mengaksesnya di dalam pengontrol menggunakan $scope.filtered.length.
Wumms
2
Itu tidak berhasil untuk saya. Log undefined, kemungkinan karena pada saat logging, variabel belum didefinisikan. Jadi bagaimana saya memastikan kode di controller dijalankan setelah variabel didefinisikan dan filter diterapkan dalam tampilan?
Ben
6
@ Ben: Saya kira ini di luar topik. Saya akan mempertimbangkan untuk membuat filter khusus misalnya jsfiddle , namun, Anda juga dapat menontonnya di dalam controller:$scope.$watch('filtered', function() { console.log('filtered:', $scope.filtered); });
Wumms
3
Versi 1.3 + tidak bekerja jika saya ingin menambahkan limitTo: person in data | filter:query as filtered | limitTo:5. Jadi saya harus menggunakan versi sebelum 1.3:person in filtered = (data | filter: query) | limitTo: 5
benjovanic
333

Untuk kelengkapan, selain jawaban sebelumnya (melakukan perhitungan orang-orang yang terlihat di dalam controller) Anda juga dapat melakukan perhitungan itu dalam template HTML Anda seperti pada contoh di bawah ini.

Dengan asumsi daftar orang Anda dalam datavariabel dan Anda memfilter orang menggunakan querymodel, kode berikut akan bekerja untuk Anda:

<p>Number of visible people: {{(data|filter:query).length}}</p>
<p>Total number of people: {{data.length}}</p>
  • {{data.length}} - mencetak jumlah orang
  • {{(data|filter:query).length}} - mencetak jumlah orang yang difilter

Perhatikan bahwa solusi ini berfungsi dengan baik jika Anda ingin menggunakan data yang difilter hanya sekali dalam satu halaman. Namun, jika Anda menggunakan data yang difilter lebih dari sekali misalnya untuk menyajikan item dan menunjukkan panjang daftar yang difilter, saya akan menyarankan menggunakan alias alias (dijelaskan di bawah) untuk AngularJS 1.3+ atau solusi yang diajukan oleh @Wumms untuk versi AngularJS sebelum 1.3.

Fitur Baru dalam Angular 1.3

Pembuat AngularJS juga memperhatikan masalah itu dan dalam versi 1.3 (beta 17) mereka menambahkan ekspresi "alias" yang akan menyimpan hasil antara pengulang setelah filter diterapkan misalnya

<div ng-repeat="person in data | filter:query as results">
    <!-- template ... -->
</div>

<p>Number of visible people: {{results.length}}</p>

The ekspresi alias akan mencegah masalah eksekusi penyaring beberapa.

Saya harap itu akan membantu.

Tom
sumber
4
Apakah ini berarti filter dijalankan dua kali?
Flash
9
Ya, ini dieksekusi dua kali.
nathancahill
11
pastikan Anda membaca jawaban @Wumms sebelum Anda memutuskan untuk menggunakan yang ini (dan Anda tidak akan) ...
epeleg
1
Nevermind, saya melihat jawabannya tidak mengandung bagian tentang ekspresi alias ketika Anda membuat komentar Anda.
Adam Goodwin
2
Jawaban ini mendukung banyak ekspresi filter tidak seperti jawaban teratas saat ini. ie){{(data|filter:query|filter:query2).length}}
chakeda
45

Cara termudah jika Anda miliki

<div ng-repeat="person in data | filter: query"></div>

Panjang data yang difilter

<div>{{ (data | filter: query).length }}</div>
ionescho
sumber
Ini paling berguna bagi siapa saja yang menggunakan arular utils dir-paginate directive karena aliasing dan alternatif pra-1.3 tidak didukung.
pcnate
Apakah ini akan menghitung data dua kali?
Jeppe
36

ngRepeat membuat salinan array ketika menerapkan filter, jadi Anda tidak bisa menggunakan array sumber untuk referensi hanya elemen yang difilter.

Dalam kasus Anda, mungkin lebih baik menerapkan filter di dalam pengontrol Anda menggunakan $filterlayanan:

function MainCtrl( $scope, filterFilter ) {
  // ...

  $scope.filteredData = myNormalData;

  $scope.$watch( 'myInputModel', function ( val ) {
    $scope.filteredData = filterFilter( myNormalData, val );
  });

  // ...
}

Dan kemudian Anda menggunakan filteredDataproperti dalam tampilan Anda. Berikut adalah Plunker yang berfungsi: http://plnkr.co/edit/7c1l24rPkuKPOS5o2qtx?p=preview

Josh David Miller
sumber
1
Apa yang saya pahami adalah bahwa saya menggunakan {{filteredData.length}}alih-alih data.length. Saya juga mengerti bahwa myInputModelmodel dipetakan ke permintaan input yang menyaring data. valakan menjadi teks yang diketik dalam input (pada dasarnya permintaan) tetapi setiap kali saya mengetik, itu berubah. Tapi apa yang ada di filterFiltersini? Saya dapat menambahkan bahwa saya memiliki customFilter saya sendiri dibuat (di mana saya dapat menentukan kunci objek yang akan dipertimbangkan untuk pemfilteran).
user109187
Betul. Juga cukup gunakan ng-repeat="person in filteredData"karena tidak ada gunanya menyaringnya dua kali. Dengan $filterlayanan, Anda dapat meminta untuk filter tertentu dengan hanya suffixing dengan "Filter", misalnya: dateFilter, jsonFilter, dll Jika Anda menggunakan filter kustom Anda sendiri, hanya menggunakan satu bukan generik filterFilter.
Josh David Miller
Bagaimana dengan menerapkan beberapa filter ke satu pengulangan, katakan Anda memiliki 2 dropdown dengan nilai dan satu bidang input teks?
alkimia
Filter hanyalah sebuah fungsi, jadi Anda hanya akan meneruskan output dari filter pertama ke filter kedua.
Josh David Miller
29

Sejak AngularJS 1.3 Anda dapat menggunakan alias:

item in items | filter:x as results

dan di suatu tempat:

<span>Total {{results.length}} result(s).</span>

Dari dokumen :

Anda juga dapat memberikan ekspresi alias opsional yang kemudian akan menyimpan hasil antara repeater setelah filter diterapkan. Biasanya ini digunakan untuk membuat pesan khusus ketika filter aktif pada pengulang, tetapi set hasil yang difilter kosong.

Misalnya: item dalam item | filter: x sebagai hasil akan menyimpan fragmen item yang diulang sebagai hasil, tetapi hanya setelah item diproses melalui filter.

Selamat Datang di
sumber
Saya tidak dapat menerapkan $scope.$watchhasil alias ini. Adakah tips untuk $broadcastmemasukkan resultsvariabel alias ?
DeBraid
25

Penting juga untuk dicatat bahwa Anda dapat menyimpan beberapa tingkat hasil dengan mengelompokkan filter

all items: {{items.length}}
filtered items: {{filteredItems.length}}
limited and filtered items: {{limitedAndFilteredItems.length}}
<div ng-repeat="item in limitedAndFilteredItems = (filteredItems = (items | filter:search) | limitTo:25)">...</div>

inilah demo biola

JeremyWeir
sumber
13

Di sini bekerja contoh Lihat di Plunker

  <body ng-controller="MainCtrl">
    <input ng-model="search" type="text">
    <br>
    Showing {{data.length}} Persons; <br>
    Filtered {{counted}}
    <ul>
      <li ng-repeat="person in data | filter:search">
        {{person.name}}
      </li>
    </ul>
  </body>

<script> 
var app = angular.module('angularjs-starter', [])

app.controller('MainCtrl', function($scope, $filter) {
  $scope.data = [
    {
      "name": "Jim", "age" : 21
    }, {
      "name": "Jerry", "age": 26
    }, {
      "name": "Alex",  "age" : 25
    }, {
      "name": "Max", "age": 22
    }
  ];

  $scope.counted = $scope.data.length; 
  $scope.$watch("search", function(query){
    $scope.counted = $filter("filter")($scope.data, query).length;
  });
});

Maksym
sumber
4
Masalah dengan pendekatan ini adalah Anda menjalankan filter dua kali: sekali di ngRepeat dan sekali di controller.
Josh David Miller
Ya, Anda benar, dapatkah Anda memposting contoh kerja berdasarkan jawaban Anda, saya ingin belajar sedikit lebih banyak filter? Terima kasih.
Maksym
2
Tentu. Inilah Plunker yang berfungsi: plnkr.co/edit/7c1l24rPkuKPOS5o2qtx?p=preview . Saya baru saja mengedit milik Anda.
Josh David Miller
10

Anda dapat melakukannya dengan 2 cara . Di template dan di Controller . Dalam template Anda dapat mengatur array yang difilter ke variabel lain, lalu menggunakannya seperti yang Anda inginkan. Inilah cara melakukannya:

<ul>
  <li data-ng-repeat="user in usersList = (users | gender:filterGender)" data-ng-bind="user.name"></li>
</ul>
 ....
<span>{{ usersList.length | number }}</span>

Jika Anda membutuhkan contoh, lihat AngularJs menghitung contoh / demo

Hazarapet Tunanyan
sumber