2016-09-07 15 views
5

ng-repeatでうまく動作する複数のフィルタがあります。しかし、コードは、実際にセットでフィルターを動作させるのに不必要に長く思えますし、もっと良い方法があるのだろうかと思っています。ここで複数のフィルターを実装する最良の方法AngularJS?

は、例えばフィルタである - このビットは、(誰もが何かアドバイスを持っていなければ)私はOKだ - それらはすべて同様の構造は、次のとおりです。

app.js

.filter('taskClient', function() { 
    return function (items, clientId) { 
     if (!clientId) { return items; } 
     var filtered = []; 
     angular.forEach(items, function(item) { 
      if (item.client) { 
       if (item.client.id === clientId) { 
        filtered.push(item); 
       } 
      } 
     }); 
     return filtered; 
    } 
}) 

とASを私は言った - これらのいくつかがあります。その後、私のNGリピートに、私は(これは維持するのは難しいと過度に長いようで、任意のより良い技術上の情報をいただければ幸いビットである)ようにそれらを実装:

タスク-index.htmlを

<md-list-item icp-task-line ng-repeat="task in TasksCtrl.tasks | taskOwner: TasksCtrl.selectedUserFilter | taskClient: TasksCtrl.clientId | taskDepartment: TasksCtrl.departmentId | taskPriority: TasksCtrl.priority | taskWithClient: TasksCtrl.withClient | taskEndDate: TasksCtrl.endDate | filter: {progress: 0} | filter: searchText | orderBy: TasksCtrl.orderTasks" class="md-2-line"></md-list-item> 

ここでどの程度のスクロールが行われているかで判断すると、私は上記のコードで私の問題を見ることができると思います。ビューのタスクの長さを取得するために(私は完了した、進行中などに分かれています)、私は再びすべてのフィルタをリストする必要があります。

これらのフィルタを実装する方法はありますか?

私はまた、this articleを読んだ後に、ステートフルフィルタと非ステートフルフィルタの違いを理解していないことに懸念しています。上記フィルタはパフォーマンスに最適化されていますか?私はあなたが本当に強力でjavascript関数filter()を、使用することをお勧め

+0

これらのフィルタを多数使用することを教えてください。表示プロセスで実際に何を達成しようとしていますか。サンプルデモが提供されれば素晴らしいでしょう。 –

+0

上記のすべてのオプションでタスクをフィルタリングすることができれば、その理由が分かりました。ただし、ロード時に適用されるのは1つだけです。チェックボックスまたはドロップダウンを使用して、すべてがngモデルを通じて実行されます。 – DJC

+0

非常に多くのフィルタを使用すると問題が発生します。それはすべての時計のフィルタが追加すると関係しています。パイプが多くなるほど、あなたは持っている時計が増え、パフォーマンスが低下します。すべてのテストを行う単一のフィルタを実装するか、代わりに多数のファクトリフィルタメソッドを使用する単一のフィルタを実装することをお勧めします(配列内に保持し、フィルタで 'forEach'を使用する)。このために使用できるデザインパターンがたくさんあります。重要なことは、連鎖フィルターの数を最小限に保つことです。 – eitanfar

答えて

0

.filter('taskClient', function() { 
    return function(items, clientId) { 
    if (!clientId) { return items; } 
    return items.filter(function(item) { 
     return item.client && item.client.id === clientId; 
    }); 
    } 
}) 
+1

いくつかの行を切り捨てる以外にも(情報をいただければ幸いです)、フィルタの適用方法を変更していません。現在のコードが正確にやっています。 – DJC

+1

いいえ、それは本当に異なっています: 'forEach'と'filter' docs ...または、かなり大きな配列で2つの実装を実行してみて、パフォーマンスの違いを見てみましょう:それは巨大になります。:-) – MarcoS

+0

素晴らしい - 私は確かにそれを行います。そこに - 知っておいてよかった。うまくいけば私はそれを少し明確にしたところで質問を編集することを参照してください - これは、これらのフィルタの実際のアプリケーションです - html ng-repeatの中で私にとってトップに見えますが、もっと良い方法があるのだろうか? – DJC

3

あなたは、たとえば、1にすべてのあなたの同様のフィルタを組み合わせることができますが(私はあなたのタスクの構造について非常におおよその仮定を作っモデル:)、私は同様に内部filter: {progress: 0}フィルタ)を挿入:

.filter('taskFilter', function() { 
    return function (items, args) { 
    return items.filter(function(item) { 
     return (!args.selectedUserFilter || item.selectedUserFilter === args.selectedUserFilter) && 
      (!args.clientId || item.client && item.client.id === args.clientId) && 
      (!args.departmentId || item.department && item.department.id === args.departmentId) && 
      (!args.priority || item.priority === args.priority) && 
      (!args.withClient || item.withClient === args.withClient) && 
      (!args.endDate || item.endDate === args.endDate) && 
      item.progress === 0; 
    }); 
    } 
}) 

今HTMLは

のように見えるかもしれません
<md-list-item icp-task-line ng-repeat="task in TasksCtrl.tasks | taskFilter: TasksCtrl | filter: searchText | orderBy: TasksCtrl.orderTasks" class="md-2-line"></md-list-item> 
+0

パフォーマンスを向上させるか、ウォッチャーを減らすか?彼らは一緒に働くだろうか? – DJC

+0

1. HTML内の連鎖フィルタは、1つのフィルタの出力が次のフィルタの入力に行き、各フィルタが受信した配列を新たに繰り返し、結合フィルタが1回だけ反復することを意味します。 2.各フィルタは時計を登録し、組み合わせたフィルタは1つの時計を登録します。 3.組み合わされたフィルターは他のフィルターと一緒に働くかもしれません、そして、その結果はHTMLフィルターに連鎖するのとまったく同じです。フィルタの両方の種類のplunker - http://plnkr.co/edit/2XUlpSz702kqcjFXsMG1?p=preview – Andriy

+0

遅延のお詫び - 私はちょうど答えを見直しに来て、これは最高の答えと思われる。私が持っている質問だけは、現在の連鎖フィルタを削除してもウォッチャーの数を減らすことはできないと思われます - これは期待されていますか?あなたのアプローチに別のパフォーマンス上のメリットがありますか? – DJC

3

私には2つのアドバイスがあります。まず、変数にフィルタ結果を取得してカウントを取得するためにすべてのフィルタを再度適用する必要がない場合は、documentationに記載されているtrack by...の前に、フィルタの末尾にas filtered_resultを追加できます。

他のアドバイスは、HTMLでフィルタを強制的に使用しないことです。 かもしれないTasksCtrl.tasksに1回フィルターし、その結果をTasksCtrl.filteredTasksプロパティに保存して、ng-repeatが少ない時計数で繰り返すことができる関数を作成する方が良い場合があります。角度フィルタでフィルタリングコードを保持する場合は、$filterを注入し、関数内で手動で実行します。

function filterTasks(){ 
    var tasks = TasksCtrl.tasks; 
    tasks = $filter('taskOwner')(tasks, TasksCtrl.selectedUserFilter); 
    tasks = $filter('taskClient')(tasks, TasksCtrl.clientId); 
    tasks = $filter('taskDepartment')(tasks, TasksCtrl.departmentId) 
    tasks = $filter('taskPriority')(tasks, TasksCtrl.priority); 
    tasks = $filter('taskWithClient')(tasks, TasksCtrl.withClient); 
    tasks = $filter('taskEndDate')(tasks, TasksCtrl.endDate) 
    tasks = $filter('filter')(tasks, {progress: 0}); 
    tasks = $filter('filter')(tasks, searchText); 
    tasks = $filter('orderBy')(tasks, TasksCtrl.orderTasks); 
    TasksCtrl.filteredTasks = tasks; 
} 
関連する問題