フィルタリングされたng-repeatデータの長さを表示する方法


438

多くのオブジェクト(JSON形式)を含むデータ配列があります。この配列の内容として、次のことが想定されます。

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

今、私はこれらの詳細を次のように表示します:

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

ここでは、クエリは、ユーザーが表示されるデータを制限できる入力フィールドにモデル化されています。

今、私は表示している人/人の現在の数を表示する別の場所があります、すなわち Showing {{data.length}} Persons

私がやりたいのは、ユーザーが人を検索し、表示されたデータがクエリに基づいてフィルタリングされると、Showing...persons現在表示されている人の値も変化することです。しかし、それは起こっていません。フィルタリングされたデータではなく、常にデータの合計人数が表示されます-フィルタリングされたデータの数を取得するにはどうすればよいですか

回答:


746

Angular 1.3以降(@Tomへのクレジット)

エイリアス式を使用します(ドキュメント:Angular 1.3.0:ngRepeat引数セクションまでスクロールします):

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

1.3より前のAngularの場合

結果を新しい変数(例:)に割り当て、filteredそれにアクセスします。

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

結果の数を表示します。

Showing {{filtered.length}} Persons

同様の例をいじる。クレジットはPawel Kozlowskiに送られます


42
これは、フィルターの実行を繰り返さない単純な答えです。
agmin 2014年

3
@ベン:はい。コントローラ内でを使用してアクセスできます$scope.filtered.length
Wumms 14年

2
それは私にはうまくいきません。ログ。ログundefinedを記録した時点では変数がまだ定義されていないためと考えられます。では、変数が定義され、フィルターがビューに適用されたに、コントローラーのコードが実行されるようにするにはどうすればよいですか?
Ben

6
@ベン:私はこれが話題から外れていると思います。私は、例えば、カスタムフィルタを作成することを検討したいjsfiddle:しかし、あなたはまた、コントローラ内部でそれを見ることができ、$scope.$watch('filtered', function() { console.log('filtered:', $scope.filtered); });
Wumms

3
1.3+バージョンは、limitTo:を追加したい場合に機能しませんでしたperson in data | filter:query as filtered | limitTo:5。したがって、1.3より前のバージョンを使用する必要がありましたperson in filtered = (data | filter: query) | limitTo: 5
。– benjovanic

332

完全を期すために、以前の回答(コントローラー内の目に見える人物の計算を実行)に加えて、以下の例のようにHTMLテンプレートでその計算を実行することもできます。

人々のリストがdata可変でありquery、モデルを使用して人々をフィルタリングすると仮定すると、次のコードが機能します。

<p>Number of visible people: {{(data|filter:query).length}}</p>
<p>Total number of people: {{data.length}}</p>
  • {{data.length}} -総人数を印刷します
  • {{(data|filter:query).length}} -フィルタリングされた人数を印刷します

ページで一度だけフィルター処理されたデータを使用する場合は、このソリューションが適切に機能することに注意してください。ただし、フィルター処理されたデータを複数回使用して、たとえばアイテムを表示し、フィルター処理されたリストの長さを表示する場合は、AngularJS 1.3+または@Wummsが1.3より前のバージョンのAngularJSに提案したソリューションのエイリアス式(以下で説明)を使用することをお勧めします。

Angular 1.3の新機能

AngularJSの作成者は、この問題にも気付き、バージョン1.3(ベータ17)では、フィルターが適用された後にリピーターの中間結果を保存する「エイリアス」式を追加しました。

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

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

別名式は、複数のフィルタの実行問題を防ぐことができます。

お役に立てば幸いです。


4
これは、フィルターが2回実行されることを意味しますか?
フラッシュ

9
はい、2回実行されます。
nathancahill 2014年

11
これを使用する前に@Wummsの回答を必ずお読みください(使用しないことになります)...
epeleg

1
気にしないでください。コメントを書き込んだときに、エイリアス式に関する部分が回答に含まれていないようです。
Adam Goodwin、2015

2
この回答は、現在の上位の回答とは異なり、複数のフィルター式をサポートしています。ie){{(data|filter:query|filter:query2).length}}
chakeda 2016年

45

あなたが持っている場合の最も簡単な方法

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

フィルタリングされたデータ長

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

これは、エイリアスとng-1.3以​​前の代替がサポートされていないため、angular utils dir-paginateディレクティブを使用するすべてのユーザーにとって最も役立ちます。
pcnate

これはデータを2回列挙しますか?
Jeppe、

36

ngRepeatはフィルターを適用するときに配列のコピーを作成するため、ソース配列を使用してフィルターされた要素のみを参照することはできません。

あなたのケースでは、$filterサービスを使用してコントローラ内にフィルタを適用する方が良いかもしれません:

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

  $scope.filteredData = myNormalData;

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

  // ...
}

そして、filteredData代わりにビューでプロパティを使用します。これが動作するPlunkerです:http ://plnkr.co/edit/7c1l24rPkuKPOS5o2qtx?p=preview


1
私が理解したのは、の{{filteredData.length}}代わりに使用することですdata.length。またmyInputModel、データをフィルタリングする入力クエリにマップされたモデルであることも理解しました。val入力(基本的にクエリ)に入力されるテキストですが、入力するたびに変化します。しかし、filterFilterここは何ですか?独自のcustomFilterを作成したことを追加することもできます(ここで、フィルター処理の対象となるオブジェクトのキーを指定できます)。
user109187 2013年

そのとおり。またng-repeat="person in filteredData"、2回フィルタリングする意味がないため、そのまま使用してください。$filter:サービス、あなただけの「フィルタ」、例えばとそれを接尾辞を付けることで、特定のフィルタを求めることができdateFilterjsonFilterあなたがあなた自身のカスタムフィルタを使用している場合などだけではなく、一般的なの1つを使用しますfilterFilter
Josh David Miller

1つのng-repeatに複数のフィルターを適用するのはどうでしょうか。値を持つ2つのドロップダウンと1つのテキスト入力フィールドがあるとします。
錬金術2013年

フィルターは単なる関数なので、最初のフィルターの出力を2番目のフィルターに渡すだけです。
Josh David Miller

29

AngularJS 1.3以降では、エイリアスを使用できます。

item in items | filter:x as results

そしてどこか:

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

ドキュメントから:

オプションのエイリアス式を指定して、フィルターが適用された後のリピーターの中間結果を保存することもできます。通常、これはリピーターでフィルターがアクティブであるが、フィルターされた結果セットが空の場合に、特別なメッセージをレンダリングするために使用されます。

次に例を示します。filter:x as resultsは、繰り返しアイテムのフラグメントを結果として格納しますが、アイテムがフィルターを介して処理された後でのみです。


$scope.$watchこのエイリアスされた結果には適用できません。$broadcastエイリアスresults変数を使用するためのヒントはありますか?
DeBraid 2016

25

フィルターをグループ化することにより、複数レベルの結果を保存できることに注意してください。

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>

ここにデモのフィドルがあります


13

ここに働いた例があります

  <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
このアプローチの問題は、フィルターを2回実行していることです。1回はngRepeatで、もう1回はコントローラーで実行します。
Josh David Miller

ええ、あなたは正しいです、あなたの答えに基づいてあなたの実際の例を投稿できますか、私はもう少しフィルターを学びたいですか?ありがとう。
Maksym 2013年

2
承知しました。これが動作するPlunkerです:plnkr.co/edit/7c1l24rPkuKPOS5o2qtx?p=preview。私はあなたのものを編集しました。
Josh David Miller

10

あなたは2つの方法でそれを行うことができます。では、テンプレートとでコントローラー。テンプレートでは、フィルターされた配列を別の変数に設定し、それを好きなように使用できます。これを行う方法は次のとおりです。

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

例が必要な場合は、AngularJsのフィルターされたカウントの例/デモをご覧ください。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.