2
2

More than 5 years have passed since last update.

Tabulatorにて、フォーマットしたセルをヘッダーフィルタで絞り込みを実装する

Posted at

去年までグリッドテーブル表示はw2uiでしたが、tabulatorに完全乗り換えたmajirouです。

tabulator はセルの値に対して、ルックアップするような形でそのセルに表示する値をformatterで指定できます。

例えば、formatter: 'money'とすれば、セルの値1000を、表示上1,000と整形してくれます。
規定値以外に関数を定義することができるので、今回はそれを行います。

完成

先に出来上がったものをCodePenに記述しました。

See the Pen tabulator sample by majirou (@majirou) on CodePen.

解説

データについて

今回の例では、以下のような「ウシ」や「ブタ」などの名前と共に、categoryという値をもつデータを扱います。
categoryには、1~5の数値が入っており、それぞれ該当する名称が別途データで提供されています。

const data = [
 { id: 1, name: 'ウシ' , category: 5},
 { id: 2, name: 'ブタ' , category: 5},
 { id: 3, name: 'トリ' , category: 4},
 { id: 4, name: 'ヒツジ' , category: 5},
 { id: 5, name: 'マグロ' , category: 1}
]

const categoryList = [
 { id: 1, name: '魚類'},
 { id: 2, name: '両生類'},
 { id: 3, name: '爬虫類'},
 { id: 4, name: '鳥類'},
 { id: 5, name: '哺乳類'},
]

tabulator本体

これをtabulatorで表示していきます。
高さやレイアウトを適当に定めて、headerFilterにてヘッダーフィルターを有効にします。

const table = new Tabulator( '#table' , {
  height: 300, 
  layout:"fitColumns", 
  data,
  columns: [
    { field: 'name', title:'Name', headeFilter: true } , 
    { field: 'category', title:'Category', headeFilter: true } 
  ]
}

image.png

headerFilter: trueを指定したので、各列のヘッダーにフィルターが付与されたデータテーブルが作成されました。

セルのフォーマット

このままではカテゴリー列は数値そのままなので、一体何のカテゴリーなのかわかりません。
1なら「魚類」、4なら「鳥類」と表示するために、「該当する値を探し、その名前を返す関数」をformatterに定義します。

  columns: [
    { field: 'name', title:'Name', headeFilter: true } , 
-    { field: 'category', title:'Category', headeFilter: true } 
+    { field: 'category', title:'Category', headerFilter: true, formatter: cell => { 
+      const categoryIndex = Object.keys(categoryList).find(f => { return categoryList[f].id === cell.getValue() })
+      return (categoryList[categoryIndex] != null) ? categoryList[categoryIndex].name : cell.getValue()
+    }}
  ]

すると、先ほど数値が表示されていた部分が、該当する「哺乳類」や「鳥類」に変わって表示されます。

image.png

動作しないヘッダーフィルター

ところが、このヘッダーフィルターにて「哺乳類」と入力しても、期待する絞り込み結果にはなりません。

image.png

実際のセル値は、1や4といった値であり、見かけ上だけがフォーマットされ「何類」か表示されているだけだからです。
これを解決するためには、headerFilterFunc に入力した値で絞り込める処理関数を定義します。

ヘッダーフィルター関数のカスタマイズ

公式ドキュメントのFilter Comparison Types項を参照すると、以下のようにサンプルがありますので、これを真似て「該当する値を探し、その名前を返す関数」を定義します。

function customHeaderFilter(headerValue, rowValue, rowData, filterParams){
    //headerValue - the value of the header filter element
    //rowValue - the value of the column in this row
    //rowData - the data for the row being filtered
    //filterParams - params object passed to the headerFilterFuncParams property
    return rowData.name == filterParams.name && rowValue < headerValue; //must return a boolean, true if it passes the filter.
}
//column definition object in table constructor
{title:"Age", field:"age", headerFilter:"input", headerFilterPlaceholder:"Max Age", headerFilterFunc:customHeaderFilter, headerFilterFuncParams:{name:"bob"}}

ポイント

  • 引数 headerValueが、ヘッダーフィルターに入力した値
  • 引数 rowValueが、セルの値

つまり、今回の例でいうと、
* headerValue が、入力した 「哺乳類」
* rowValueが、1,4,5などの値

となりますので、入力した値にマッチするかを正規表現で判定し、true/falseを返すことで、フィルタリング関数として動作します。

  columns:[              
    { title:"Name", field:"name" ,headerFilter: true},
    { title:'Category', field: 'category', headerFilter: true, formatter: cell => { 
      const categoryIndex = Object.keys(categoryList).find(f => { return categoryList[f].id === cell.getValue() })
      return (categoryList[categoryIndex] != null) ? categoryList[categoryIndex].name : cell.getValue()
-    }
+    }, headerFilterFunc: (headerValue, rowValue, rowData, filterParams) => {
+      const regexp = new RegExp(headerValue)
+      const categoryIndex = Object.keys(categoryList).find(f => { return categoryList[f].id === rowValue })
+      return regexp.test(categoryList[categoryIndex].name) 
    }}

以上で、冒頭の内容が出来上がります。

セル値の置換について

わざわざ自前で関数を用意しなければ、表示に則したヘッダーフィルターが有効にならないと記載しました。

これに関して、formatterで表示上を変えるのではなく、mutator を使えばセルの値自体を置換することができます。
従って、headerFilterFuncを定義しなくても上述のようなヘッダーフィルターは可能になります。

ただし、表示するだけなら問題ないのですが、例えばその行のデータを使って別途フォームを表示し、サーバーとやりとりするなどが発生しうる場合、
mutator を行ってしまうと、値そのものが変わってしまうので、サーバーに送る際に置換した値を元の値に戻す処理などが必要になります。

まとめ

  • formatterした値を絞り込むには、headerFilterFuncに入力値で絞り込む関数を定義する
  • 絞り込むだけならmutatorでセル値を変えてしまう方が楽。ただし、データそのものが置き換わるので注意
2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2