Vue.jsで filterBy フィルタの結果の件数を取得したくなったら

filterBy フィルタで絞り込んだ結果の件数を表示したり、0件の時にメッセージを表示したいということはままある。が、以下のように普通にfilterBy フィルタを使っても、絞りこまれた結果の件数は取得できない。

<div v-for="item in items | filterBy 'hello'">

似たようなことを考える人はいるもので、issueがあった。

github.com

作者いわく、

If you need to access the filtered result, you have to either use a custom filter or a computed property Array.

ということ。自分でフィルタを定義するか、絞りこまれた結果を返すcomputed propertyを定義せよ、とのこと。

computed: {
  filteredItems: function () {
    return this.items.filter(function (item) {
      return item.indexOf('helllo') > -1;
    });
  }
}

とcomputed propertyと定義すれば、以下のように結果の件数を利用できる。

<p v-show="filteredItems.length > 0">
結果は{{filteredItems.length}}件です
</p>
<p v-show="filteredItems.length == 0">
結果はないよ
</p>

「えー、自分で書かなければいけないの?」とも思うけれど、必要最低限の仕組みを提供して、それ以外は各自で用意せよ、という方針は、Vue.jsのシンプルさ、学習コストの低さに繋がっているのだと理解している。利用者の要求に無闇に応じて、filterBy フィルタが拡張され続けたら、あらゆるニーズに対応できるが、使い始めた人がオプションの数やその組み合わせによる挙動の違いに戸惑う代物になっていたのでは。

標準のfilterBy フィルタは絞り込むためのキーを複数指定できたり、と良い点もあって、必要であればコンポーネントから以下のようにfilterBy APIを呼び出せばよろしい。

computed: {
  filteredItems: function () {
    return this.$options.filters.filterBy(this.items, 'hello');
  }
}