Filtrelenen ng-tekrar verilerinin uzunluğu nasıl görüntülenir?


438

Birçok nesne (JSON biçimi) içeren bir veri dizisi var. Bu dizinin içeriği olarak aşağıdakiler kabul edilebilir:

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

Şimdi, bu detayları şu şekilde görüntülüyorum:

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

Burada sorgu, kullanıcının görüntülenen verileri kısıtlayabileceği bir giriş alanına modellenir.

Şimdi, görüntülenmekte olan kişi / kişi sayısını görüntülediğim başka bir konumum var, yani Showing {{data.length}} Persons

Ne yapmak istiyorum kullanıcı bir kişi aradığında ve görüntülenen veri sorguya göre filtre, Showing...personsaynı zamanda şu anda gösterilen insanların değerini değiştirmek olduğunu. Ama olmuyor. Filtrelenmiş olandan ziyade her zaman toplam kişi verilerini görüntüler - filtrelenmiş veri sayısını nasıl alabilirim?

Yanıtlar:


746

Açısal 1.3+ için (@Tom'a kredi)

Bir takma ad ifadesi kullanın (Dokümanlar: Angular 1.3.0: ngRepeat , Arguments bölümüne ilerleyin ):

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

1.3 öncesi açısal için

Sonuçları yeni bir değişkene (örn. filtered) Atayın ve ona erişin:

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

Sonuç sayısını göster:

Showing {{filtered.length}} Persons

Bir keman benzer bir örnek . Krediler Pawel Kozlowski'ye gidiyor


42
Bu, filtre yürütmeyi tekrar etmeyen basit bir cevaptır.
agmin

3
@ Ben: Evet. Düğmesini kullanarak denetleyicinin içinden erişebilirsiniz $scope.filtered.length.
Wumms

2
Bu benim için işe yaramıyor. Günlükler undefined, büyük olasılıkla günlüğe kaydedildiği sırada değişken henüz tanımlanmamıştır. Değişken tanımlandıktan ve filtre görünümde uygulandıktan sonra denetleyicideki kodun çalıştırılmasını nasıl sağlayabilirim ?
Ben

6
@Ben: Sanırım bu konu dışı gidiyor. Örneğin, jsfiddle gibi özel bir filtre oluşturmayı düşünürdüm , ancak denetleyicinin içinde de izleyebilirsiniz:$scope.$watch('filtered', function() { console.log('filtered:', $scope.filtered); });
Wumms

3
1.3 + sürümü limitTo: eklemek istedim işe yaramadı person in data | filter:query as filtered | limitTo:5. Bu yüzden 1.3 sürümünden önce kullanmak zorunda kaldım:person in filtered = (data | filter: query) | limitTo: 5
benjovanic

332

Tamlık için, önceki yanıtlara ek olarak (denetleyici içinde görünür kişilerin hesaplamasını yapın) bu hesaplamaları aşağıdaki örnekte olduğu gibi HTML şablonunuzda da yapabilirsiniz.

Kişi listenizin datadeğişken olduğunu ve querymodeli kullanarak kişileri filtrelediğinizi varsayarsak , aşağıdaki kod sizin için çalışır:

<p>Number of visible people: {{(data|filter:query).length}}</p>
<p>Total number of people: {{data.length}}</p>
  • {{data.length}} - toplam kişi sayısını yazdırır
  • {{(data|filter:query).length}} - filtrelenmiş kişi sayısını yazdırır

Filtrelenmiş verileri bir sayfada yalnızca bir kez kullanmak istiyorsanız bu çözümün iyi çalıştığını unutmayın . Daha örneğin mevcut olan öğelerin ve süzüldü liste uzunluğunu göstermek için bir kez daha veri filtre kullanır, ancak ben kullanarak öneririm takma ekspresyonunu angularjs için (aşağıda tarif edilen) 1.3 + veya önerdiği çözüm @Wumms 1.3 önce angularjs sürümü için.

Açısal 1.3'te Yeni Özellik

AngularJS yaratıcıları da problemin farkına vardılar ve versiyon 1.3'te (beta 17) filtreler uygulandıktan sonra tekrarlayıcının ara sonuçlarını saklayacak "takma ad" ifadesi eklediler.

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

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

Takma ifadesi birden filtre yürütme sorunu önleyecektir.

Umarım yardımcı olur.


4
Bu, filtrenin iki kez yürütüldüğü anlamına mı gelir?
Flash

9
Evet, iki kez yürütülür.
nathancahill

11
Bunu kullanmaya karar vermeden önce @Wumms cevabını okuduğunuzdan emin olun (ve yapmayacaksınız) ...
epeleg

1
Boşver, yorumunuzu yaptığınızda cevabın takma ad ifadesi ile ilgili kısmı içermediğini görüyorum.
Adam Goodwin

2
Bu yanıt, geçerli üst yanıttan farklı olarak birden çok filtre ifadesini destekler. ie){{(data|filter:query|filter:query2).length}}
chakeda

45

Eğer sahip olmanın en kolay yolu

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

Filtrelenmiş veri uzunluğu

<div>{{ (data | filter: query).length }}</div>

Bu, kenar yumuşatma dir-paginate yönergesi kullanan herkes için yararlıdır, çünkü takma ad ve pre-1.3 alternatifi desteklenmez.
pcnate

Bu, verileri iki kez numaralandıracak mı?
Jeppe

36

ngRepeat, bir filtre uyguladığında dizinin bir kopyasını oluşturur; bu nedenle, yalnızca filtre uygulanmış öğelere başvurmak için kaynak diziyi kullanamazsınız.

Sizin durumunuzda, $filterservisi kullanarak kontrol cihazınızın içine filtre uygulamak daha iyi olabilir :

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

  $scope.filteredData = myNormalData;

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

  // ...
}

Ve sonra filteredDataözelliği görünümünüzde kullanırsınız. İşte çalışan bir Plunker: http://plnkr.co/edit/7c1l24rPkuKPOS5o2qtx?p=preview


1
Anladığım şey bunun {{filteredData.length}}yerine kullanmam data.length. Ayrıca myInputModel, verileri filtreleyen giriş sorgusuna eşlenen model olduğunu anladım . valgirdi (temelde sorgu) yazılan metin olurdu ama her yazdığımda, değişir. Ama filterFilterburada ne var? Kendi customFilter oluşturulan (burada filtreleme için dikkate alınacak nesnenin hangi anahtarını belirtebilirsiniz) ekleyebilir.
user109187

Doğru. Ayrıca sadece ng-repeat="person in filteredData"iki kez filtrelemenin anlamı olmadığı için kullanın . İle $filter: hizmet, sadece "Filtre", örneğin ile son eklemeli belirli bir filtre için sorabilir dateFilter, jsonFilter, kendi özel filtre kullanıyorsanız, vb sadece yerine jenerik o birini kullanabilirsiniz filterFilter.
Josh David Miller

Bir ng tekrarına birden fazla filtre uygulamadan bahsedelim. Değerler ve bir metin giriş alanı içeren 2 açılır listeniz var mı?
simyalama

Filtre sadece bir işlevdir, bu nedenle ilk filtrenin çıkışını ikinci filtreye geçirirsiniz.
Josh David Miller

29

AngularJS 1.3'ten bu yana takma adları kullanabilirsiniz:

item in items | filter:x as results

ve bir yerlerde:

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

Gönderen docs :

Filtreler uygulandıktan sonra tekrarlayıcının ara sonuçlarını saklayacak isteğe bağlı bir takma ad ifadesi de sağlayabilirsiniz. Bu genellikle tekrarlayıcı üzerinde bir filtre aktifken özel bir mesaj oluşturmak için kullanılır, ancak filtrelenen sonuç kümesi boştur.

Örneğin: öğelerdeki öğe | filter: x, sonuç olarak yinelenen öğelerin parçasını sonuç olarak, ancak öğeler filtre aracılığıyla işlendikten sonra saklar.


Başvuramıyorum $scope.$watchBu takma adı alınmış sonuca . Diğer değişkenin $broadcasting. results
DeBraid

25

Filtreleri gruplandırarak birden çok düzeyde sonuç depolayabileceğinizi not etmek de yararlıdır

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>

İşte bir demo keman


13

İşte çalıştı örnek Plunker bakın

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


4
Bu yaklaşımla ilgili sorun, filtreyi iki kez çalıştırmanızdır: bir kez ngRepeat ve bir kez de kontrolörde.
Josh David Miller

Evet, haklısın, cevabına göre çalışma örneğini gönderebilir misin, biraz daha filtre öğrenmek ister miyim? Teşekkürler.
Maksym

2
Elbette. İşte çalışan Plunker: plnkr.co/edit/7c1l24rPkuKPOS5o2qtx?p=preview . Sizinkini yeni düzenledim.
Josh David Miller

10

Bunu 2 yolla yapabilirsiniz . Gelen şablona ve Kontrolör . Şablonda, filtrelenmiş dizinizi başka bir değişkene ayarlayabilir ve ardından istediğiniz gibi kullanabilirsiniz. İşte nasıl yapılacağı:

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

Örneklere ihtiyacınız varsa, AngularJs filtrelenmiş sayım örneklerine / demolarına bakın

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.