{{row.id}}</td> <td>{{row.name}}</td> <td>{{r..." /> AngularJSの複雑なfilterを、関数で実現する - 戯言

戯言

つらつらと気づいたことを書いていきます。人狼とか。

AngularJSの複雑なfilterを、関数で実現する


AngularJSを使い始めて、まず誰もが便利だなと感じるのは、ng-repeat での繰り返しと、filter を使った検索ではないでしょうか。いろいろな紹介サイトでも、記述例が見受けられます。
<input type="text" ng-model="query.$" placeholder="全項目で検索">

<table><tbody>
<tr ng-repeat="row in rows | filter:query">
<td>{{row.id}}</td>
<td>{{row.name}}</td>
<td>{{row.address}}</td>
<td>{{row.note}}</td>
</tr>
</tbody></table>
これだけで、rowの全ての要素(id、name、address、note)のどこかに、input text で入力された内容を含んでいるものだけが、表示されます。

row.idに含んでてもいいし、row.nameに含んでいいし、row.addressに含んでいてもよい。「長野」と入力すれば、nameの長野さんも、addressの長野県も引っかかります。



では、row.nameのみに対して絞り込みをしたい場合。こうなります。
<input type="text" ng-model="query.name" placeholder="名前で検索">
filter の対象を name のみにするために、ng-model="query.$" の部分を ng-model="query.name" に変えればよいのです。
この場合は、nameの長野さんは検索対象となるが、addressに長野県とあってもひっかかりません。



では、nameとnoteの2項目のみを検索の対象にしたいという場合は、どのようにすればよいのでしょうか?

「複雑な検索を行う場合は、directiveを使いましょう。」ってのも間違いじゃないんだけど、directiveを使わずとも、単純な検索フィルタ用の関数を利用することもできます。
<input type="text" ng-model="query" placeholder="nameとnoteを対象に検索">

<table><tbody>
<tr ng-repeat="row in rows | filter:search">
<td>{{row.id}}</td>
<td>{{row.name}}</td>
<td>{{row.address}}</td>
<td>{{row.note}}</td>
</tr>
</tbody></table>
// JS
$scope.search = function(line){
    // 各行をlineオブジェクトで受け、trueを返した行だけがマッチ
    if (line.name.indexOf($scope.query) != -1 ||
        line.note.indexOf($scope.query) != -1){
	    return true;
    }
    return false;
};
これで、nameとnoteのみに対して、検索をすることができます。



AngularJSを扱いはじめた当初は、今まで数十行も書いて実現していたロジックを、とてもシンプルに書くことができて、非常に便利で生産性が高いと感じますよね。でも、ちょっと複雑なことをしようとすると、躓いてしまうことがよくあります。これは、日本語の解説サイトがまだまだ充実していないことも原因でしょうね。

もっと、AngularJSが広まってほしい。
便利だよ!



関連記事

管理者にだけ表示を許可する